■ USB通信2
![]()
■ PIC18F14K50 HIDクラス LED 点灯/消灯制御&表示
<試作品仕様>
・PC(Windows)上のボタンスイッチ×4個をクリックすると PIC18F40K50のキバン上の対応するLEDがON/OFFすること
・PCとPIC間のUSB通信はHIDクラスとする。
・ボタンスイッチはLEDがONしているときは赤色、OFFの時は灰色とする。
・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと
★ PC側のソフト(Windows)は こちらを参照願います
<試作品回路図>(→回路図のPDFファイル)
<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています
<プログラム例>
//Ledx4 オンオフ制御
//PIC18F14K50
#include "usb.h"
#include "HardwareProfile.h"
#include "usb_function_hid.h"
//システムクロック48MHz(= 12MHz x 4PLL)
#pragma config CPUDIV = NOCLKDIV ,USBDIV = OFF, PCLKEN = ON
#pragma config FOSC = HS, PLLEN = ON, HFOFST = OFF
#pragma config PWRTEN = ON, BOREN = OFF, MCLRE = OFF, BORV = 30
#pragma config WDTEN = OFF, LVP = OFF, FCMEN = OFF, IESO = OFF
#pragma config CP0 = OFF, XINST = OFF
// USB関連バッファ、変数定義
#pragma udata usbram2
unsigned char ReceivedDataBuffer[64];
unsigned char SendBuf[64];
#pragma udata
USB_HANDLE USBOutHandle = 0;
USB_HANDLE USBInHandle = 0;
BOOL blinkStatusValid = TRUE;
//グローバル変数定義
BYTE counter;
BOOL blinkStatusValid;
//コマンド定数定義
typedef enum
{
CHECK = 0x30,
POUT = 0x31,
PIN = 0x32,
AIN = 0x33,
RESET = 0xFF
}TYPE_CMD;
void BlinkUSBStatus(void);
void ProcessIO(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);
// 割り込みベクタ定義
#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = 0x08
void Remapped_High_ISR (void)
{
_asm goto YourHighPriorityISRCode _endasm
}
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = 0x18
void Remapped_Low_ISR (void)
{
_asm goto YourLowPriorityISRCode _endasm
}
// 割り込み処理関数
#pragma code
#pragma interrupt YourHighPriorityISRCode
void YourHighPriorityISRCode()
{
USBDeviceTasks();
}
#pragma interruptlow YourLowPriorityISRCode
void YourLowPriorityISRCode()
{
}
#pragma code
void main(void)
{
ANSEL = 0x00; // デジタルに設定
TRISC = 0; //LEDポート(RC0-RC3) :out
LATC = 0; //全LED消灯
//USB関連
USBDeviceInit(); // USB初期化
USBInHandle = 0;
USBOutHandle = 0;
blinkStatusValid = TRUE; // USB目印LED有効化
USBDeviceAttach(); // USB割り込み有効化
while(1)
{
//USB接続中なら送受信実行
if((USBDeviceState >= CONFIGURED_STATE)&&(USBSuspendControl!=1))
ProcessIO(); // コマンド実行
}
}
//ユーザーアプリの入出力処理関数
void ProcessIO(void)
{
//データ受信処理
if(!HIDRxHandleBusy(USBOutHandle))
{
blinkStatusValid = FALSE;
SendBuf[0] = ReceivedDataBuffer[0];
SendBuf[1] = ReceivedDataBuffer[1];
//コマンドの処理
switch(ReceivedDataBuffer[0]) // コマンドコードチェック //受信データの先頭バイトチェック
{
//接続確認応答
case CHECK: //0x30
SendBuf[2] = 'O';
SendBuf[3] = 'K';
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);
break;
//LED制御の場合
case POUT: //0x31,
if(ReceivedDataBuffer[1] == 0x31){ //LED0の場合
if(ReceivedDataBuffer[2] == 0x31)
{ mLED_1_On(); } //LED:ON
else if(ReceivedDataBuffer[2] == 0x30)
{ mLED_1_Off(); } //LED:OFF
SendBuf[2] = mLED_1 + 0x30;
}
else if(ReceivedDataBuffer[1] == 0x32){ //LED1の場合
if(ReceivedDataBuffer[2] == 0x31)
{ mLED_2_On(); }
else if(ReceivedDataBuffer[2] == 0x30)
{ mLED_2_Off(); }
SendBuf[2] = mLED_2 + 0x30;
}
else if(ReceivedDataBuffer[1] == 0x33){ //LED2の場合
if(ReceivedDataBuffer[2] == 0x31)
{ mLED_3_On(); }
else if(ReceivedDataBuffer[2] == 0x30)
{ mLED_3_Off(); }
SendBuf[2] = mLED_3 + 0x30;
}
else if(ReceivedDataBuffer[1] == 0x34){ //LED3の場合
if(ReceivedDataBuffer[2] == 0x31)
{ mLED_4_On(); }
else if(ReceivedDataBuffer[2] == 0x30)
{ mLED_4_Off(); }
SendBuf[2] = mLED_4 + 0x30;
}
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);
break;
default:
break;
}
// 次の受信実行
USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}
}
/******************************************************************
************** USB Callback Functions *****************************
*******************************************************************/
/******************************************************************
* Function: void USBCBSuspend(void)
******************************************************************/
void USBCBSuspend(void)
{
}
/*******************************************************************
* Function: void USBCBWakeFromSuspend(void)
*******************************************************************/
void USBCBWakeFromSuspend(void)
{
}
/********************************************************************
* Function: void USBCB_SOF_Handler(void)
*******************************************************************/
void USBCB_SOF_Handler(void)
{
}
/*******************************************************************
* Function: void USBCBErrorHandler(void)
*******************************************************************/
void USBCBErrorHandler(void)
{
}
/*******************************************************************
* Function: void USBCBCheckOtherReq(void)
*******************************************************************/
void USBCBCheckOtherReq(void)
{
USBCheckHIDRequest();
}//end
/*******************************************************************
* Function: void USBCBStdSetDscHandler(void)
*******************************************************************/
void USBCBStdSetDscHandler(void)
{
}//end
/*******************************************************************
* Function: void USBCBInitEP(void)
*******************************************************************/
void USBCBInitEP(void)
{
//enable the HID endpoint
USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
//Re-arm the OUT endpoint for the next packet
USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}
/*******************************************************************
* Function: void USBCBSendResume(void)
******************************************************************/
void USBCBSendResume(void)
{
static WORD delay_count;
if(USBGetRemoteWakeupStatus() == TRUE)
{
//Verify that the USB bus is in fact suspended, before we send
//remote wakeup signalling.
if(USBIsBusSuspended() == TRUE)
{
USBMaskInterrupts();
//Clock switch to settings consistent with normal USB operation.
USBCBWakeFromSuspend();
USBSuspendControl = 0;
USBBusIsSuspended = FALSE; //So we don't execute this code again,
delay_count = 3600U;
do
{
delay_count--;
}while(delay_count);
//Now drive the resume K-state signalling onto the USB bus.
USBResumeControl = 1; // Start RESUME signaling
delay_count = 1800U; // Set RESUME line for 1-13 ms
do
{
delay_count--;
}while(delay_count);
USBResumeControl = 0; //Finished driving resume signalling
USBUnmaskInterrupts();
}
}
}
/*******************************************************************
* Function: BOOL USER_USB_CALLBACK_EVENT_HANDLER(
*******************************************************************/
BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size)
{
switch(event)
{
case EVENT_TRANSFER:
break;
case EVENT_SOF:
USBCB_SOF_Handler();
break;
case EVENT_SUSPEND:
USBCBSuspend();
break;
case EVENT_RESUME:
USBCBWakeFromSuspend();
break;
case EVENT_CONFIGURED:
USBCBInitEP();
break;
case EVENT_SET_DESCRIPTOR:
USBCBStdSetDscHandler();
break;
case EVENT_EP0_REQUEST:
USBCBCheckOtherReq();
break;
case EVENT_BUS_ERROR:
USBCBErrorHandler();
break;
case EVENT_TRANSFER_TERMINATED:
break;
default:
break;
}
return TRUE;
}
//-------------------------------------------------------------------------------
/********************************************************************
FileName: usb_descriptors.c
Dependencies: See INCLUDES section
Processor: PIC18 or PIC24 USB Microcontrollers
Hardware: The code is natively intended to be used on the following
hardware platforms: PICDEM・FS USB Demo Board,
PIC18F87J50 FS USB Plug-In Module, or
Explorer 16 + PIC24 USB PIM. The firmware may be
modified for use on other USB platforms by editing the
HardwareProfile.h file.
Complier: Microchip C18 (for PIC18) or C30 (for PIC24)
Company: Microchip Technology, Inc.
Software License Agreement:
The software supplied herewith by Microchip Technology Incorporated
(the 鼎ompany・ for its PICョ Microcontroller is intended and
supplied to you, the Company痴 customer, for use solely and
exclusively on Microchip PIC Microcontroller products. The
software is owned by the Company and/or its supplier, and is
protected under applicable copyright laws. All rights are reserved.
Any use in violation of the foregoing restrictions may subject the
user to criminal sanctions under applicable laws, as well as to
civil liability for the breach of the terms and conditions of this
license.
THIS SOFTWARE IS PROVIDED IN AN 鄭S IS・CONDITION. NO WARRANTIES,
WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*********************************************************************
-usb_descriptors.c-
-------------------------------------------------------------------
Filling in the descriptor values in the usb_descriptors.c file:
-------------------------------------------------------------------
[Device Descriptors]
The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type.
This type is defined in usb_ch9.h Each entry into this structure
needs to be the correct length for the data type of the entry.
[Configuration Descriptors]
The configuration descriptor was changed in v2.x from a structure
to a BYTE array. Given that the configuration is now a byte array
each byte of multi-byte fields must be listed individually. This
means that for fields like the total size of the configuration where
the field is a 16-bit value "64,0," is the correct entry for a
configuration that is only 64 bytes long and not "64," which is one
too few bytes.
The configuration attribute must always have the _DEFAULT
definition at the minimum. Additional options can be ORed
to the _DEFAULT attribute. Available options are _SELF and _RWU.
These definitions are defined in the usb_device.h file. The
_SELF tells the USB host that this device is self-powered. The
_RWU tells the USB host that this device supports Remote Wakeup.
[Endpoint Descriptors]
Like the configuration descriptor, the endpoint descriptors were
changed in v2.x of the stack from a structure to a BYTE array. As
endpoint descriptors also has a field that are multi-byte entities,
please be sure to specify both bytes of the field. For example, for
the endpoint size an endpoint that is 64 bytes needs to have the size
defined as "64,0," instead of "64,"
Take the following example:
// Endpoint Descriptor //
0x07, //the size of this descriptor //
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP02_IN, //EndpointAddress
_INT, //Attributes
0x08,0x00, //size (note: 2 bytes)
0x02, //Interval
The first two parameters are self-explanatory. They specify the
length of this endpoint descriptor (7) and the descriptor type.
The next parameter identifies the endpoint, the definitions are
defined in usb_device.h and has the following naming
convention:
_EP<##>_<dir>
where ## is the endpoint number and dir is the direction of
transfer. The dir has the value of either 'OUT' or 'IN'.
The next parameter identifies the type of the endpoint. Available
options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not
typically used because the default control transfer endpoint is
not defined in the USB descriptors. When _ISO option is used,
addition options can be ORed to _ISO. Example:
_ISO|_AD|_FE
This describes the endpoint as an isochronous pipe with adaptive
and feedback attributes. See usb_device.h and the USB
specification for details. The next parameter defines the size of
the endpoint. The last parameter in the polling interval.
-------------------------------------------------------------------
Adding a USB String
-------------------------------------------------------------------
A string descriptor array should have the following format:
rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={
sizeof(sdxxx),DSC_STR,<text>};
The above structure provides a means for the C compiler to
calculate the length of string descriptor sdxxx, where xxx is the
index number. The first two bytes of the descriptor are descriptor
length and type. The rest <text> are string texts which must be
in the unicode format. The unicode format is achieved by declaring
each character as a word type. The whole text string is declared
as a word array with the number of characters equals to <size>.
<size> has to be manually counted and entered into the array
declaration. Let's study this through an example:
if the string is "USB" , then the string descriptor should be:
(Using index 02)
rom struct{byte bLength;byte bDscType;word string[3];}sd002={
sizeof(sd002),DSC_STR,'U','S','B'};
A USB project may have multiple strings and the firmware supports
the management of multiple strings through a look-up table.
The look-up table is defined as:
rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002};
The above declaration has 3 strings, sd000, sd001, and sd002.
Strings can be removed or added. sd000 is a specialized string
descriptor. It defines the language code, usually this is
US English (0x0409). The index of the string must match the index
position of the USB_SD_Ptr array, &sd000 must be in position
USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on.
The look-up table USB_SD_Ptr is used by the get string handler
function.
-------------------------------------------------------------------
The look-up table scheme also applies to the configuration
descriptor. A USB device may have multiple configuration
descriptors, i.e. CFG01, CFG02, etc. To add a configuration
descriptor, user must implement a structure similar to CFG01.
The next step is to add the configuration descriptor name, i.e.
cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0]
is a dummy place holder since configuration 0 is the un-configured
state according to the definition in the USB specification.
********************************************************************/
/*********************************************************************
* Descriptor specific type definitions are defined in:
* usb_device.h
*
* Configuration options are defined in:
* usb_config.h
********************************************************************/
#ifndef __USB_DESCRIPTORS_C
#define __USB_DESCRIPTORS_C
/** INCLUDES *******************************************************/
#include "usb.h"
#include "usb_function_hid.h"
/** CONSTANTS ******************************************************/
#if defined(__18CXX)
#pragma romdata
#endif
/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc= //デバイスデスクリプタ
{
0x12, // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type
0x0200, // USB Spec Release Number in BCD format
0x00, // Class Code //HIDクラス
0x00, // Subclass code //未定義(=汎用)
0x00, // Protocol code
USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h
0x04D8, // Vendor ID //ベンダーID
0x003F, // Product ID: Custom HID demo //プロダクトID
0x0002, // Device release number in BCD format
0x01, // Manufacturer string index
0x02, // Product string index
0x00, // Device serial number string index
0x01 // Number of possible configurations
};
/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={ //コンフィグデスクリプタ
/* Configuration Descriptor */
0x09, //sizeof(USB_CFG_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type
0x29,0x00, // Total length of data for this cfg
1, // Number of interfaces in this cfg
1, // Index value of this configuration
0, // Configuration string index
_DEFAULT | _SELF, // Attributes, see usb_device.h
50, // Max power consumption (2X mA) //最大消費電流50mA
/* Interface Descriptor */ //インターフェースデスクリプタ
0x09, //sizeof(USB_INTF_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type
0, // Interface Number
0, // Alternate Setting Number
2, // Number of endpoints in this intf //エンドポイントの数
HID_INTF, // Class code
0, // Subclass code
0, // Protocol code
0, // Interface string index
/* HID Class-Specific Descriptor *///HIDクラスの仕様に係るデスクリプタ部分
0x09, //sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes
DSC_HID, // HID descriptor type
0x11,0x01, // HID Spec Release Number in BCD format (1.11)
0x00, // Country Code (0x00 for Not supported)
HID_NUM_OF_DSC, // Number of class descriptors, see usbcfg.h
DSC_RPT, // Report descriptor type
HID_RPT01_SIZE,0x00, //sizeof(hid_rpt01), // Size of the report descriptor
/* Endpoint Descriptor */ // エンドポイントデスクリプタ
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_IN, //EndpointAddress
_INTERRUPT, //Attributes
0x40,0x00, //size
0x01, //Interval
/* Endpoint Descriptor */
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_OUT, //EndpointAddress
_INTERRUPT, //Attributes
0x40,0x00, //size
0x01 //Interval
};
//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};
//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};
//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'S','i','m','p','l','e',' ','H','I','D',' ',
'D','e','v','i','c','e',' ','D','e','m','o'
}};
//Class specific descriptor - HID
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{
0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1)
0x09, 0x01, // Usage (Vendor Usage 1)
0xA1, 0x01, // Collection (Application)
0x19, 0x01, // Usage Minimum
0x29, 0x40, // Usage Maximum //64 input usages total (0x01 to 0x40)
0x15, 0x01, // Logical Minimum (data bytes in the report may have minimum value = 0x00)
0x25, 0x40, // Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
0x75, 0x08, // Report Size: 8-bit field size
0x95, 0x40, // Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
0x81, 0x00, // Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
0x19, 0x01, // Usage Minimum
0x29, 0x40, // Usage Maximum //64 output usages total (0x01 to 0x40)
0x91, 0x00, // Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
0xC0} // End Collection
};
//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
(ROM BYTE *ROM)&configDescriptor1
};
//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
(ROM BYTE *ROM)&sd000,
(ROM BYTE *ROM)&sd001,
(ROM BYTE *ROM)&sd002
};
/** EOF usb_descriptors.c ***************************************************/
#endif
<実行結果>
接続ボタンをクリックした後、LED0、LED2、LED3を点灯させたところです。
尚、PIC18F14K50のキバン上には本テーマと関係ない部品が多々搭載されています。
![]() |
![]() |
■ PIC18F14K50 HIDクラス スイッチの状態&電圧 読込・表示
<試作品仕様>
・PCとPIC間のUSB通信はHIDクラスとする。
・PIC18F14K50のキバン上のスイッチ×3個を押すと PC(Windows)上の対応するovalShape×3個の色が 灰色→オレンジ色に変わること
・PCとPIC間のUSB通信はHIDクラスとする。
・可変抵抗器×3個により設定される電圧をPIC18F14K50の内蔵ADコンバータで読込、この電圧値[V]をPC上の対応するテキストボックス×3個に表示のこと。
・テキストボックスに表示される電圧[V]は、小数点以下2桁とする。
・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと
★ PCのソフト(VC++)は こちらを参照願います
<試作品回路図>(→回路図のPDFファイル)

<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

<プログラム例>
//
//USB HIDクラス
#include "usb.h"
#include "HardwareProfile.h"
#include "usb_function_hid.h"
/** コンフィギュレーション ***********************/
#pragma config CPUDIV = NOCLKDIV ,USBDIV = OFF, PCLKEN = ON
#pragma config FOSC = HS, PLLEN = ON, HFOFST = OFF
#pragma config PWRTEN = ON, BOREN = OFF, MCLRE = OFF, BORV = 30
#pragma config WDTEN = OFF, LVP = OFF, FCMEN = OFF, IESO = OFF
#pragma config CP0 = OFF, XINST = OFF
/******** USB関連バッファ、変数定義 ****/
#pragma udata usbram2
unsigned char ReceivedDataBuffer[64];
unsigned char SendBuf[64];
#pragma udata
USB_HANDLE USBOutHandle = 0;
USB_HANDLE USBInHandle = 0;
BOOL blinkStatusValid = TRUE;
/**** グローバル変数定義 ***/
BYTE counter;
BOOL blinkStatusValid;
/*** コマンド定数定義 ***/
typedef enum
{
CHECK = 0x30,
POUT = 0x31,
PIN = 0x32,
AIN = 0x33,
RESET = 0xFF
}TYPE_CMD;
void BlinkUSBStatus(void);
void ProcessIO(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);
//割り込みベクタ定義
#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = 0x08
void Remapped_High_ISR (void)
{
_asm goto YourHighPriorityISRCode _endasm
}
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = 0x18
void Remapped_Low_ISR (void)
{
_asm goto YourLowPriorityISRCode _endasm
}
//割り込み処理関数
#pragma code
#pragma interrupt YourHighPriorityISRCode
void YourHighPriorityISRCode()
{
USBDeviceTasks();
}
#pragma interruptlow YourLowPriorityISRCode
void YourLowPriorityISRCode()
{
}
#pragma code
void main(void)
{
ANSEL = 0x00; // デジタルに設定
ANSELH =0x07; // AN8,9,10のみアナログ
TRISA = 0xFF; // RA0-5入力
TRISB = 0x7F; // RB7(TX)以外すべて入力
LATC = 0; // 出力初期化
TRISC = 0xF0; // RC6,7アナログ入力、RC0-3出力
// ADC初期化
ADCON0 = 0; // 停止
ADCON1 = 0; // VDD-Vss
ADCON2 = 0xBE; // 右詰め,20Tad,Fosc/64
//USB関連
USBDeviceInit(); // USB初期化
USBInHandle = 0;
USBOutHandle = 0;
blinkStatusValid = TRUE; // USB目印LED有効化
USBDeviceAttach(); // USB割り込み有効化
while(1)
{
//USB接続中なら送受信実行
if((USBDeviceState >= CONFIGURED_STATE)&&(USBSuspendControl!=1))
ProcessIO(); // コマンド実行
}
}
//ユーザーアプリの入出力処理関数
void ProcessIO(void)
{
//データ受信処理
if(!HIDRxHandleBusy(USBOutHandle))
{
blinkStatusValid = FALSE;
SendBuf[0] = ReceivedDataBuffer[0];
SendBuf[1] = ReceivedDataBuffer[1];
switch(ReceivedDataBuffer[0]) // コマンドコードチェック
{
//接続確認応答
case CHECK:
SendBuf[2] = 'O';
SendBuf[3] = 'K';
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);
break;
//入力ピン状態要求と応答の場合
case PIN :
if(ReceivedDataBuffer[1] == 0x31){
if(sw1)
SendBuf[2] = 0x31;
else
SendBuf[2] = 0x30;
}
else if(ReceivedDataBuffer[1] == 0x32){
if(sw2)
SendBuf[2] = 0x31;
else
SendBuf[2] = 0x30;
}
else if(ReceivedDataBuffer[1] == 0x33){
if(sw3)
SendBuf[2] = 0x31;
else
SendBuf[2] = 0x30;
}
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);
break;
/***** アナログ入力要求と応答 *****/
case AIN:
/* チャネル選択後A/D変換 AN8,AN9, An10 */
ADCON0 = ((ReceivedDataBuffer[1]-0x31+8) << 2) + 0x01;
ADCON0bits.GO = 1; // A/D変換開始
while(ADCON0bits.NOT_DONE); // 変換完了待ち
SendBuf[2] = ADRESL; // 送信バッファにセット
SendBuf[3] = ADRESH;
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64);
break;
default:
break;
}
// 次の受信実行
USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}
}
/******************************************************************
************** USB Callback Functions *****************************
*******************************************************************/
/******************************************************************
* Function: void USBCBSuspend(void)
******************************************************************/
void USBCBSuspend(void)
{
}
/*******************************************************************
* Function: void USBCBWakeFromSuspend(void)
*******************************************************************/
void USBCBWakeFromSuspend(void)
{
}
/********************************************************************
* Function: void USBCB_SOF_Handler(void)
*******************************************************************/
void USBCB_SOF_Handler(void)
{
}
/*******************************************************************
* Function: void USBCBErrorHandler(void)
*******************************************************************/
void USBCBErrorHandler(void)
{
}
/*******************************************************************
* Function: void USBCBCheckOtherReq(void)
*******************************************************************/
void USBCBCheckOtherReq(void)
{
USBCheckHIDRequest();
}//end
/*******************************************************************
* Function: void USBCBStdSetDscHandler(void)
*******************************************************************/
void USBCBStdSetDscHandler(void)
{
}//end
/*******************************************************************
* Function: void USBCBInitEP(void)
*******************************************************************/
void USBCBInitEP(void)
{
//enable the HID endpoint
USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
//Re-arm the OUT endpoint for the next packet
USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}
/*******************************************************************
* Function: void USBCBSendResume(void)
******************************************************************/
void USBCBSendResume(void)
{
static WORD delay_count;
if(USBGetRemoteWakeupStatus() == TRUE)
{
//Verify that the USB bus is in fact suspended, before we send
//remote wakeup signalling.
if(USBIsBusSuspended() == TRUE)
{
USBMaskInterrupts();
//Clock switch to settings consistent with normal USB operation.
USBCBWakeFromSuspend();
USBSuspendControl = 0;
USBBusIsSuspended = FALSE; //So we don't execute this code again,
delay_count = 3600U;
do
{
delay_count--;
}while(delay_count);
//Now drive the resume K-state signalling onto the USB bus.
USBResumeControl = 1; // Start RESUME signaling
delay_count = 1800U; // Set RESUME line for 1-13 ms
do
{
delay_count--;
}while(delay_count);
USBResumeControl = 0; //Finished driving resume signalling
USBUnmaskInterrupts();
}
}
}
/*******************************************************************
* Function: BOOL USER_USB_CALLBACK_EVENT_HANDLER(
*******************************************************************/
BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size)
{
switch(event)
{
case EVENT_TRANSFER:
break;
case EVENT_SOF:
USBCB_SOF_Handler();
break;
case EVENT_SUSPEND:
USBCBSuspend();
break;
case EVENT_RESUME:
USBCBWakeFromSuspend();
break;
case EVENT_CONFIGURED:
USBCBInitEP();
break;
case EVENT_SET_DESCRIPTOR:
USBCBStdSetDscHandler();
break;
case EVENT_EP0_REQUEST:
USBCBCheckOtherReq();
break;
case EVENT_BUS_ERROR:
USBCBErrorHandler();
break;
case EVENT_TRANSFER_TERMINATED:
break;
default:
break;
}
return TRUE;
}
//----------------------------------------------------
/********************************************************************
FileName: usb_descriptors.c
Dependencies: See INCLUDES section
Processor: PIC18 or PIC24 USB Microcontrollers
Hardware: The code is natively intended to be used on the following
hardware platforms: PICDEM・FS USB Demo Board,
PIC18F87J50 FS USB Plug-In Module, or
Explorer 16 + PIC24 USB PIM. The firmware may be
modified for use on other USB platforms by editing the
HardwareProfile.h file.
Complier: Microchip C18 (for PIC18) or C30 (for PIC24)
Company: Microchip Technology, Inc.
Software License Agreement:
The software supplied herewith by Microchip Technology Incorporated
(the 鼎ompany・ for its PICョ Microcontroller is intended and
supplied to you, the Company痴 customer, for use solely and
exclusively on Microchip PIC Microcontroller products. The
software is owned by the Company and/or its supplier, and is
protected under applicable copyright laws. All rights are reserved.
Any use in violation of the foregoing restrictions may subject the
user to criminal sanctions under applicable laws, as well as to
civil liability for the breach of the terms and conditions of this
license.
THIS SOFTWARE IS PROVIDED IN AN 鄭S IS・CONDITION. NO WARRANTIES,
WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*********************************************************************
-usb_descriptors.c-
-------------------------------------------------------------------
Filling in the descriptor values in the usb_descriptors.c file:
-------------------------------------------------------------------
[Device Descriptors]
The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type.
This type is defined in usb_ch9.h Each entry into this structure
needs to be the correct length for the data type of the entry.
[Configuration Descriptors]
The configuration descriptor was changed in v2.x from a structure
to a BYTE array. Given that the configuration is now a byte array
each byte of multi-byte fields must be listed individually. This
means that for fields like the total size of the configuration where
the field is a 16-bit value "64,0," is the correct entry for a
configuration that is only 64 bytes long and not "64," which is one
too few bytes.
The configuration attribute must always have the _DEFAULT
definition at the minimum. Additional options can be ORed
to the _DEFAULT attribute. Available options are _SELF and _RWU.
These definitions are defined in the usb_device.h file. The
_SELF tells the USB host that this device is self-powered. The
_RWU tells the USB host that this device supports Remote Wakeup.
[Endpoint Descriptors]
Like the configuration descriptor, the endpoint descriptors were
changed in v2.x of the stack from a structure to a BYTE array. As
endpoint descriptors also has a field that are multi-byte entities,
please be sure to specify both bytes of the field. For example, for
the endpoint size an endpoint that is 64 bytes needs to have the size
defined as "64,0," instead of "64,"
Take the following example:
// Endpoint Descriptor //
0x07, //the size of this descriptor //
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP02_IN, //EndpointAddress
_INT, //Attributes
0x08,0x00, //size (note: 2 bytes)
0x02, //Interval
The first two parameters are self-explanatory. They specify the
length of this endpoint descriptor (7) and the descriptor type.
The next parameter identifies the endpoint, the definitions are
defined in usb_device.h and has the following naming
convention:
_EP<##>_<dir>
where ## is the endpoint number and dir is the direction of
transfer. The dir has the value of either 'OUT' or 'IN'.
The next parameter identifies the type of the endpoint. Available
options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not
typically used because the default control transfer endpoint is
not defined in the USB descriptors. When _ISO option is used,
addition options can be ORed to _ISO. Example:
_ISO|_AD|_FE
This describes the endpoint as an isochronous pipe with adaptive
and feedback attributes. See usb_device.h and the USB
specification for details. The next parameter defines the size of
the endpoint. The last parameter in the polling interval.
-------------------------------------------------------------------
Adding a USB String
-------------------------------------------------------------------
A string descriptor array should have the following format:
rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={
sizeof(sdxxx),DSC_STR,<text>};
The above structure provides a means for the C compiler to
calculate the length of string descriptor sdxxx, where xxx is the
index number. The first two bytes of the descriptor are descriptor
length and type. The rest <text> are string texts which must be
in the unicode format. The unicode format is achieved by declaring
each character as a word type. The whole text string is declared
as a word array with the number of characters equals to <size>.
<size> has to be manually counted and entered into the array
declaration. Let's study this through an example:
if the string is "USB" , then the string descriptor should be:
(Using index 02)
rom struct{byte bLength;byte bDscType;word string[3];}sd002={
sizeof(sd002),DSC_STR,'U','S','B'};
A USB project may have multiple strings and the firmware supports
the management of multiple strings through a look-up table.
The look-up table is defined as:
rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002};
The above declaration has 3 strings, sd000, sd001, and sd002.
Strings can be removed or added. sd000 is a specialized string
descriptor. It defines the language code, usually this is
US English (0x0409). The index of the string must match the index
position of the USB_SD_Ptr array, &sd000 must be in position
USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on.
The look-up table USB_SD_Ptr is used by the get string handler
function.
-------------------------------------------------------------------
The look-up table scheme also applies to the configuration
descriptor. A USB device may have multiple configuration
descriptors, i.e. CFG01, CFG02, etc. To add a configuration
descriptor, user must implement a structure similar to CFG01.
The next step is to add the configuration descriptor name, i.e.
cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0]
is a dummy place holder since configuration 0 is the un-configured
state according to the definition in the USB specification.
********************************************************************/
/*********************************************************************
* Descriptor specific type definitions are defined in:
* usb_device.h
*
* Configuration options are defined in:
* usb_config.h
********************************************************************/
#ifndef __USB_DESCRIPTORS_C
#define __USB_DESCRIPTORS_C
/** INCLUDES *******************************************************/
#include "usb.h"
#include "usb_function_hid.h"
/** CONSTANTS ******************************************************/
#if defined(__18CXX)
#pragma romdata
#endif
/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
0x12, // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type
0x0200, // USB Spec Release Number in BCD format
0x00, // Class Code
0x00, // Subclass code
0x00, // Protocol code
USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h
0x04D8, // Vendor ID
0x003F, // Product ID: Custom HID demo
0x0002, // Device release number in BCD format
0x01, // Manufacturer string index
0x02, // Product string index
0x00, // Device serial number string index
0x01 // Number of possible configurations
};
/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
/* Configuration Descriptor */
0x09, //sizeof(USB_CFG_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type
0x29,0x00, // Total length of data for this cfg
1, // Number of interfaces in this cfg
1, // Index value of this configuration
0, // Configuration string index
_DEFAULT | _SELF, // Attributes, see usb_device.h
50, // Max power consumption (2X mA)
/* Interface Descriptor */
0x09, //sizeof(USB_INTF_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type
0, // Interface Number
0, // Alternate Setting Number
2, // Number of endpoints in this intf
HID_INTF, // Class code
0, // Subclass code
0, // Protocol code
0, // Interface string index
/* HID Class-Specific Descriptor */
0x09, //sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes
DSC_HID, // HID descriptor type
0x11,0x01, // HID Spec Release Number in BCD format (1.11)
0x00, // Country Code (0x00 for Not supported)
HID_NUM_OF_DSC, // Number of class descriptors, see usbcfg.h
DSC_RPT, // Report descriptor type
HID_RPT01_SIZE,0x00, //sizeof(hid_rpt01), // Size of the report descriptor
/* Endpoint Descriptor */
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_IN, //EndpointAddress
_INTERRUPT, //Attributes
0x40,0x00, //size
0x01, //Interval
/* Endpoint Descriptor */
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_OUT, //EndpointAddress
_INTERRUPT, //Attributes
0x40,0x00, //size
0x01 //Interval
};
//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};
//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};
//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'S','i','m','p','l','e',' ','H','I','D',' ',
'D','e','v','i','c','e',' ','D','e','m','o'
}};
//Class specific descriptor - HID
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{
0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1)
0x09, 0x01, // Usage (Vendor Usage 1)
0xA1, 0x01, // Collection (Application)
0x19, 0x01, // Usage Minimum
0x29, 0x40, // Usage Maximum //64 input usages total (0x01 to 0x40)
0x15, 0x01, // Logical Minimum (data bytes in the report may have minimum value = 0x00)
0x25, 0x40, // Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
0x75, 0x08, // Report Size: 8-bit field size
0x95, 0x40, // Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
0x81, 0x00, // Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
0x19, 0x01, // Usage Minimum
0x29, 0x40, // Usage Maximum //64 output usages total (0x01 to 0x40)
0x91, 0x00, // Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
0xC0} // End Collection
};
//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
(ROM BYTE *ROM)&configDescriptor1
};
//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
(ROM BYTE *ROM)&sd000,
(ROM BYTE *ROM)&sd001,
(ROM BYTE *ROM)&sd002
};
/** EOF usb_descriptors.c ***************************************************/
#endif
<実行結果>
・接続ボタンをクリックしてUSB接続をした後に スイッチボタンSW1とSW3を押した時のPCのフォーム画面です。
・ovalShapeがオレンジ色になっているスイッチはON状態をあらわし、灰色はOFF状態の場合です。
・テキストボックスに表示されている値は、PIC18F14K50が読み込んだ電圧値で、小数点以下2桁で表示されています。
・PIC18F14K50のキバン上のスイッチ×3個を押すと PC(Windows)上の対応するovalShape×3個の色が 灰色→オレンジ色に変わること
・PCとPIC間のUSB通信はHIDクラスとする。
・可変抵抗器×3個により設定される電圧をPIC18F14K50内蔵ADコンバータで読込、この電圧値[V]をPC上の対応するテキストボックス×3個に表示のこと。
・テキストボックスに表示される電圧[V]は、小数点以下2桁とする。
・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと

■ PIC32MX795F512L HIDクラス LED点灯/消灯、ADコンバータ読込・表示
<試作品仕様>
・PCとPIC間のUSB通信はHIDクラスとする。
・PC(Windows)上のボタンスイッチ×4個をクリックすると PIC32MX795F512Lのキバン上の対応するLEDがON/OFFすること
・PCとPIC間のUSB通信はHIDクラスとする。
・ボタンスイッチはLEDがONしているときは赤色、OFFの時は灰色とする。
・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと
・PIC32MX795F512Lのキバン上のスイッチ×3個を押すと PC(Windows)上の対応するovalShape×3個の色が 灰色→オレンジ色に変わること
・可変抵抗器により設定される電圧をPIC32MX795F512L内蔵ADコンバータで読込、この電圧値[V]をPC上のテキストボックスに表示のこと。
・テキストボックスに表示される電圧[V]は、小数点以下2桁とする。
・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと
★ PC側のソフト(Windows)は こちらを参照願います
<試作品回路図>(→回路図のPDFファイル)

<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

<プログラム例>
//main.c //32MX795
#include "./USB/usb.h"
#include "HardwareProfile.h"
#include "./USB/usb_function_hid.h"
//システムクロック80MHz ペリフェラルクロック80MHz
#pragma config UPLLEN = ON // USB PLL Enabled
#pragma config FPLLMUL = MUL_20 // PLL Multiplier
#pragma config UPLLIDIV = DIV_2 // USB PLL Input Divider
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider
#pragma config FPLLODIV = DIV_1 // PLL Output Divider
#pragma config FPBDIV = DIV_1 // Peripheral Clock divisor
#pragma config FWDTEN = OFF // Watchdog Timer
#pragma config WDTPS = PS1 // Watchdog Timer Postscale
#pragma config FCKSM = CSDCMD // Clock Switching & Fail Safe Clock Monitor
#pragma config OSCIOFNC = OFF // CLKO Enable
#pragma config POSCMOD = HS // Primary Oscillator
#pragma config IESO = OFF // Internal/External Switch-over
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (KLO was off)
#pragma config FNOSC = PRIPLL // Oscillator Selection
#pragma config CP = OFF // Code Protect
#pragma config BWP = OFF // Boot Flash Write Protect
#pragma config PWP = OFF // Program Flash Write Protect
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select
#define RX_DATA_BUFFER_ADDRESS
#define TX_DATA_BUFFER_ADDRESS
unsigned char ReceivedDataBuffer[64] RX_DATA_BUFFER_ADDRESS;
unsigned char ToSendDataBuffer[64] TX_DATA_BUFFER_ADDRESS;
unsigned char SendBuf[64];
USB_HANDLE USBOutHandle = 0; //USB handle. Must be initialized to 0 at startup.
USB_HANDLE USBInHandle = 0; //USB handle. Must be initialized to 0 at startup.
BOOL blinkStatusValid = TRUE;
void BlinkUSBStatus(void);
void ProcessIO(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);
WORD_VAL ReadPOT(void);
unsigned int AdcValue;
int main(void)
{
SYSTEMConfigPerformance(80000000); //システム最適化
DDPCONbits.JTAGEN = 0; //JTAG無効化
AD1PCFG = 0xFFFF; //全RBポートデジタルピンとして使用
AD1PCFGbits.PCFG9 = 0; //AN9:アナログ
TRISBbits.TRISB9 = 1;
TRISAbits.TRISA2 = 0;
TRISAbits.TRISA3 = 0;
TRISAbits.TRISA4 = 0;
TRISAbits.TRISA5 = 0;
LATAbits.LATA2 = 0;
LATAbits.LATA3 = 0;
LATAbits.LATA4 = 0;
LATAbits.LATA5 = 0;
TRISDbits.TRISD6=1;
TRISDbits.TRISD7=1;
TRISDbits.TRISD13=1;
//AD1CON1レジスタの設定
AD1CON1bits.ON = 1; //A/Dコンバータモジュール有効
// AD1CON1bits.FRZ = 0; //デバッグモードに於いても動作継続
AD1CON1bits.SIDL = 0; //アイドルモード中もモジュール動作継続
AD1CON1bits.FORM2 = 0; //AD1CON1bits.FORM2-AD1CON1bits.FORM0のセットで出力データ形式指定 → 000:16ビット符号なし整数形式
AD1CON1bits.FORM1 = 0; //011:符号付固定16ビット小数 010:固定小数16ビット 001:符号付き整数16ビット 000:16ビット符号なし整数
AD1CON1bits.FORM0 = 0; //111:符号付32ビット固定小数 110:32ビット固定小数 101:符号付32ビット整数 100=32ビット符号なし整数
//★ Michrochip データシートDS61104 では000、100がIntegerとなっているがUnsigned Integerの誤植である。
AD1CON1bits.SSRC2 = 1; //AD1CON1bits.SSRC2-AD1CON1bits.SSRC0 のセットでトリガーソースを指定
AD1CON1bits.SSRC1 = 1; //111: 内蔵カウンタでサンプリングを終了させ変換を開始する
AD1CON1bits.SSRC0 = 1; //(参考)000: SAMPビットでサンプリングを終了し変換を開始する
AD1CON1bits.CLRASAM = 0;//AD変換割り込み時の変換停止 0:次の変換値でオーバーライト
AD1CON1bits.ASAM = 0; //SAMPビットのセットでサンプリングを開始する。(参考)1: 自動開始(前の変換終了後すぐサンプリングを開始する)
AD1CON1bits.SAMP = 0; //サンプリング停止
//AD1CON2レジスタの設定
AD1CON2bits.VCFG2 = 0; //リファレンス選択//AD1CON2bits.VCFG2 - AD1CON2bits.VCFG0(VCFG<2:0>)の3ビットでセット
AD1CON2bits.VCFG1 = 0; //★000:リファレンス電圧 → Vdd -Vss
AD1CON2bits.VCFG0 = 0; //(参考)001:リファレンス電圧 → 外部入力 - Vss 他
AD1CON2bits.OFFCAL = 0; //較正モード設定 0:サンプルホールドアンプSHAの入力はAD1CHSレジスタとAD1CSSLレジスタで制御される
AD1CON2bits.CSCNA = 1; //★マルチプレクサMUXAでのスキャン: する
AD1CON2bits.SMPI3 = 0; //割り込みタイミング AD1CON2bits.SMPI3 - AD1CON2bits.SMPI0(SMPI<3:0>)の4ビットでセット
AD1CON2bits.SMPI2 = 0; //0000: AD変換完了毎の割り込み発生(割り込み有効の場合)
AD1CON2bits.SMPI1 = 0; //(参考)0011: 4サンプルのAD変換終了後 割り込み発生(割り込み有効の場合)
AD1CON2bits.SMPI0 = 0; //
AD1CON2bits.BUFM = 0; //バッファーを1個の16ワードバッファとする。 (参考)1: 2組の8ワードバッファーとする
AD1CON2bits.ALTS = 0; //常にMUXAを入力マルチプレクサにする (参考)1: MUXA,MUXBを交互につかう
//AD1CON3レジスタの設定
AD1CON3bits.ADRC = 0; //AD変換クロック源選択//0: PBCLK(Peripheral Bus Clock) (参考)1: A/D内臓RCクロック
AD1CON3bits.SAMC4 = 1; //AD1CON3bits.SAMC4 - AD1CON3bits.SAMC0(SAMC<4:0>)の5ビットでセット
AD1CON3bits.SAMC3 = 1; //アクイジションタイム(Tad(クロック周期)×N)設定(ホールドキャパシタ充電所要時間)
AD1CON3bits.SAMC2 = 1; //1111: 31Tad
AD1CON3bits.SAMC1 = 1; //(参考)0001: 1Tad 0010: 2Tad 0011: 3Tad ・・・・
AD1CON3bits.SAMC0 = 1; //
AD1CON3bits.ADCS7 = 0; //AD変換時間の設定/AD1CON3bits.ADCS7 - AD1CON3bits.ADCS0(ADCS<7:0>)の8ビットでセット
//AD変換完了フラグAD1CON1bits.DONEにより、AD変換完了を検知する場合は設定不要
AD1CON3bits.ADCS6 = 0; //AD変換完了までののクロック数選択ビット
AD1CON3bits.ADCS5 = 0; //0000 0101: 1Tad = 6Tpb (Tpb: PBCLKの周期)
AD1CON3bits.ADCS4 = 0; //(参考) 0000 0000: 1Tad = 2Tpb
AD1CON3bits.ADCS3 = 0; // 0000 0001: 1Tad = 3Tpb
AD1CON3bits.ADCS2 = 1; // 0000 0010: 1Tad = 4Tpb
AD1CON3bits.ADCS1 = 0; // ・・・・
AD1CON3bits.ADCS0 = 1; // 1111 1111: 1Tad = 512Tpb
//AD1CHSレジスタの設定 //SHAの+端子とー端子への接続(ポート)設定
//マルチプレクサ:MUXB側
AD1CHSbits.CH0NB = 0; //負側入力選択ビット: 0:VR- 、1:AN1
AD1CHSbits.CH0SB3 = 0; //正側入力選択ビット//0000:AN0, 0001:AN1, 0011:AN2 .... 1111: AN15
AD1CHSbits.CH0SB2 = 0; //★MUXAだけを使うので、CH0SB0-CH0SB3は出力に無関係
AD1CHSbits.CH0SB1 = 0; //
AD1CHSbits.CH0SB0 = 0; //
//マルチプレクサ:MUXA側
AD1CHSbits.CH0NA = 0; //負側入力選択ビット: 0:VR- 、1:AN1
// AD1CHSbits.CH0SA3 = 0; //正側入力選択ビット//0000:AN0, 0001:AN1, 0010:AN2 .... 1111: AN15
// AD1CHSbits.CH0SA2 = 1; //0100マルチプレクサMUXAの正側入力: AN4
// AD1CHSbits.CH0SA1 = 0; //
// AD1CHSbits.CH0SA0 = 0; //
AD1CHSbits.CH0SA = 9; //AN9
//AD1PCFGレジスタの設定 //アナログ入力orデジタル入力選択 //1:デジタル、 0:アナログ
// ★デバイスリセットでは全ビット0となるためデフォルトではアナログ入力となるのでデジタルで使う多重ピンは、コンフィグレーションでデジタル設定が必要!!
AD1PCFGbits.PCFG15 = 1;//RB15/AN15
AD1PCFGbits.PCFG14 = 1;//RB14/AN14
AD1PCFGbits.PCFG13 = 1;//RB13/AN13
AD1PCFGbits.PCFG12 = 1;//RB12/AN12
AD1PCFGbits.PCFG11 = 1;//RB11/AN11
AD1PCFGbits.PCFG10 = 1;//RB10/AN10
AD1PCFGbits.PCFG9 = 0;//RB9/AN9 //アナログ
AD1PCFGbits.PCFG8 = 1;//RB8/AN8
AD1PCFGbits.PCFG7 = 1;//RB7/AN7
AD1PCFGbits.PCFG6 = 1;//RB6/AN6
AD1PCFGbits.PCFG5 = 1;//RB5/AN5
AD1PCFGbits.PCFG4 = 1;//RB4/AN4
AD1PCFGbits.PCFG3 = 1;//RB3/AN3
AD1PCFGbits.PCFG2 = 1;//RB2/AN2
AD1PCFGbits.PCFG1 = 1;//RB1/AN1
AD1PCFGbits.PCFG0 = 1;//RB0/AN0
// AD1CSSLレジスタの設定
//読み込むチャンネル(入力端子)をセットする//0:スキャンしない 1:スキャンする
AD1CSSLbits.CSSL15 = 0; //AN15
AD1CSSLbits.CSSL14 = 0; //AN14
AD1CSSLbits.CSSL13 = 0; //AN13
AD1CSSLbits.CSSL12 = 0; //AN12
AD1CSSLbits.CSSL11 = 0; //AN11
AD1CSSLbits.CSSL10 = 0; //AN10
AD1CSSLbits.CSSL9 = 1; //AN9 //スキャンする
AD1CSSLbits.CSSL8 = 0; //AN8
AD1CSSLbits.CSSL7 = 0; //AN7
AD1CSSLbits.CSSL6 = 0; //AN6
AD1CSSLbits.CSSL5 = 0; //AN5
AD1CSSLbits.CSSL4 = 0; //AN4
AD1CSSLbits.CSSL3 = 0; //AN3
AD1CSSLbits.CSSL2 = 0; //AN2
AD1CSSLbits.CSSL0 = 0; //AN0
//USB関係
USBDeviceInit();
USBOutHandle = 0;
USBInHandle = 0;
blinkStatusValid = TRUE;
USBDeviceAttach();
while(1)
{
// USB接続中なら送受信実行
if((USBDeviceState >= CONFIGURED_STATE)&&(USBSuspendControl!=1))ProcessIO();
}
}
void ProcessIO(void)
{
if(!HIDRxHandleBusy(USBOutHandle))
{
switch(ReceivedDataBuffer[0]) //コマンドの種類判定
{
//接続確認応答
case 0x30: //
SendBuf[2] = 'O';
SendBuf[3] = 'K';
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64); //PC側に送信
break;
case 0x80: //LED 点灯/消灯制御
switch(ReceivedDataBuffer[1])
{
case 0x30: //RA2
if(ReceivedDataBuffer[2] == 0x30)
{
LATAbits.LATA2 = 0; //消灯
SendBuf[2] = 0x30;
}
else
{
LATAbits.LATA2 = 1; //点灯
SendBuf[2] = 0x31;
}
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64); //PC側に送信
break;
case 0x31: //RA3
if(ReceivedDataBuffer[2] == 0x30)
{
LATAbits.LATA3 = 0;
SendBuf[3] = 0x30;
}
else
{
LATAbits.LATA3 = 1;
SendBuf[3] = 0x31;
}
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64); //PC側に送信
break;
case 0x32: //RA4
if(ReceivedDataBuffer[2] == 0x30)
{
LATAbits.LATA4 = 0;
SendBuf[4] = 0x30;
}
else
{
LATAbits.LATA4 = 1;
SendBuf[4] = 0x31;
}
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64); //PC側に送信
break;
case 0x33: //RA5
if(ReceivedDataBuffer[2] == 0x30)
{
LATAbits.LATA5 = 0;
SendBuf[5] = 0x30;
}
else
{
LATAbits.LATA5 = 1;
SendBuf[5] = 0x31;
}
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64); //PC側に送信
break;
default :
break;
}
case 0x81: //スイッチの状態検出
if(ReceivedDataBuffer[1] == 0x31){
if(PORTDbits.RD13 == 0)
SendBuf[2] = 0x30;
else
SendBuf[2] = 0x31;
}
else if(ReceivedDataBuffer[1] == 0x32){
if(PORTDbits.RD6 == 0)
SendBuf[2] = 0x30;
else
SendBuf[2] = 0x31;
}
else if(ReceivedDataBuffer[1] == 0x33){
if(PORTDbits.RD7 == 0)
SendBuf[2] = 0x30;
else
SendBuf[2] = 0x31;
}
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64); //PC側に送信
break;
case 0x82: //VR電圧検出
AD1CON1bits.SAMP =1; //サンプリング開始
while(!AD1CON1bits.DONE); //AD変換終了フラグがたつ(1になるまで)待つ
AdcValue = ADC1BUF0; //ADC1のバッファーからAD変換結果を読込む//★ADC1BUF1ではない
ToSendDataBuffer[2] = AdcValue; //下位8ビット at 10ビット
ToSendDataBuffer[3] = AdcValue >> 8; //上位2ビット at 10ビット
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&ToSendDataBuffer[0],64); //PC側に送信
break;
}
//次の受信実行
USBOutHandle = HIDRxPacket(HID_EP, (BYTE*)&ReceivedDataBuffer, 64);
}
}
// ******************************************************************************************************
// ************** USB Callback Functions ****************************************************************
// ******************************************************************************************************
void USBCBSuspend(void)
{
}
void USBCBWakeFromSuspend(void)
{
}
void USBCB_SOF_Handler(void)
{
}
void USBCBErrorHandler(void)
{
}
void USBCBCheckOtherReq(void)
{
USBCheckHIDRequest();
}
void USBCBStdSetDscHandler(void)
{
}
void USBCBInitEP(void)
{
//enable the HID endpoint
USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
//Re-arm the OUT endpoint for the next packet
USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}
void USBCBSendResume(void)
{
static WORD delay_count;
if(USBGetRemoteWakeupStatus() == TRUE)
{
if(USBIsBusSuspended() == TRUE)
{
USBMaskInterrupts();
//Clock switch to settings consistent with normal USB operation.
USBCBWakeFromSuspend();
USBSuspendControl = 0;
USBBusIsSuspended = FALSE; //So we don't execute this code again,
//until a new suspend condition is detected.
delay_count = 3600U;
do
{
delay_count--;
}while(delay_count);
//Now drive the resume K-state signalling onto the USB bus.
USBResumeControl = 1; // Start RESUME signaling
delay_count = 1800U; // Set RESUME line for 1-13 ms
do
{
delay_count--;
}while(delay_count);
USBResumeControl = 0; //Finished driving resume signalling
USBUnmaskInterrupts();
}
}
}
BOOL USER_USB_CALLBACK_EVENT_HANDLER(int event, void *pdata, WORD size)
{
switch(event)
{
case EVENT_TRANSFER:
//Add application specific callback task or callback function here if desired.
break;
case EVENT_SOF:
USBCB_SOF_Handler();
break;
case EVENT_SUSPEND:
USBCBSuspend();
break;
case EVENT_RESUME:
USBCBWakeFromSuspend();
break;
case EVENT_CONFIGURED:
USBCBInitEP();
break;
case EVENT_SET_DESCRIPTOR:
USBCBStdSetDscHandler();
break;
case EVENT_EP0_REQUEST:
USBCBCheckOtherReq();
break;
case EVENT_BUS_ERROR:
USBCBErrorHandler();
break;
case EVENT_TRANSFER_TERMINATED:
break;
default:
break;
}
return TRUE;
}
//--------------------------------------------------------------------
/********************************************************************
FileName: usb_descriptors.c
Dependencies: See INCLUDES section
Processor: PIC18 or PIC24 USB Microcontrollers
Hardware: The code is natively intended to be used on the following
hardware platforms: PICDEM?FS USB Demo Board,
PIC18F87J50 FS USB Plug-In Module, or
Explorer 16 + PIC24 USB PIM. The firmware may be
modified for use on other USB platforms by editing the
HardwareProfile.h file.
Complier: Microchip C18 (for PIC18) or C30 (for PIC24)
Company: Microchip Technology, Inc.
Software License Agreement:
The software supplied herewith by Microchip Technology Incorporated
(the 鼎ompany? for its PICョ Microcontroller is intended and
supplied to you, the Company痴 customer, for use solely and
exclusively on Microchip PIC Microcontroller products. The
software is owned by the Company and/or its supplier, and is
protected under applicable copyright laws. All rights are reserved.
Any use in violation of the foregoing restrictions may subject the
user to criminal sanctions under applicable laws, as well as to
civil liability for the breach of the terms and conditions of this
license.
THIS SOFTWARE IS PROVIDED IN AN 鄭S IS?CONDITION. NO WARRANTIES,
WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*********************************************************************
-usb_descriptors.c-
-------------------------------------------------------------------
Filling in the descriptor values in the usb_descriptors.c file:
-------------------------------------------------------------------
[Device Descriptors]
The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type.
This type is defined in usb_ch9.h Each entry into this structure
needs to be the correct length for the data type of the entry.
[Configuration Descriptors]
The configuration descriptor was changed in v2.x from a structure
to a BYTE array. Given that the configuration is now a byte array
each byte of multi-byte fields must be listed individually. This
means that for fields like the total size of the configuration where
the field is a 16-bit value "64,0," is the correct entry for a
configuration that is only 64 bytes long and not "64," which is one
too few bytes.
The configuration attribute must always have the _DEFAULT
definition at the minimum. Additional options can be ORed
to the _DEFAULT attribute. Available options are _SELF and _RWU.
These definitions are defined in the usb_device.h file. The
_SELF tells the USB host that this device is self-powered. The
_RWU tells the USB host that this device supports Remote Wakeup.
[Endpoint Descriptors]
Like the configuration descriptor, the endpoint descriptors were
changed in v2.x of the stack from a structure to a BYTE array. As
endpoint descriptors also has a field that are multi-byte entities,
please be sure to specify both bytes of the field. For example, for
the endpoint size an endpoint that is 64 bytes needs to have the size
defined as "64,0," instead of "64,"
Take the following example:
// Endpoint Descriptor //
0x07, //the size of this descriptor //
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP02_IN, //EndpointAddress
_INT, //Attributes
0x08,0x00, //size (note: 2 bytes)
0x02, //Interval
The first two parameters are self-explanatory. They specify the
length of this endpoint descriptor (7) and the descriptor type.
The next parameter identifies the endpoint, the definitions are
defined in usb_device.h and has the following naming
convention:
_EP<##>_<dir>
where ## is the endpoint number and dir is the direction of
transfer. The dir has the value of either 'OUT' or 'IN'.
The next parameter identifies the type of the endpoint. Available
options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not
typically used because the default control transfer endpoint is
not defined in the USB descriptors. When _ISO option is used,
addition options can be ORed to _ISO. Example:
_ISO|_AD|_FE
This describes the endpoint as an isochronous pipe with adaptive
and feedback attributes. See usb_device.h and the USB
specification for details. The next parameter defines the size of
the endpoint. The last parameter in the polling interval.
-------------------------------------------------------------------
Adding a USB String
-------------------------------------------------------------------
A string descriptor array should have the following format:
rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={
sizeof(sdxxx),DSC_STR,<text>};
The above structure provides a means for the C compiler to
calculate the length of string descriptor sdxxx, where xxx is the
index number. The first two bytes of the descriptor are descriptor
length and type. The rest <text> are string texts which must be
in the unicode format. The unicode format is achieved by declaring
each character as a word type. The whole text string is declared
as a word array with the number of characters equals to <size>.
<size> has to be manually counted and entered into the array
declaration. Let's study this through an example:
if the string is "USB" , then the string descriptor should be:
(Using index 02)
rom struct{byte bLength;byte bDscType;word string[3];}sd002={
sizeof(sd002),DSC_STR,'U','S','B'};
A USB project may have multiple strings and the firmware supports
the management of multiple strings through a look-up table.
The look-up table is defined as:
rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002};
The above declaration has 3 strings, sd000, sd001, and sd002.
Strings can be removed or added. sd000 is a specialized string
descriptor. It defines the language code, usually this is
US English (0x0409). The index of the string must match the index
position of the USB_SD_Ptr array, &sd000 must be in position
USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on.
The look-up table USB_SD_Ptr is used by the get string handler
function.
-------------------------------------------------------------------
The look-up table scheme also applies to the configuration
descriptor. A USB device may have multiple configuration
descriptors, i.e. CFG01, CFG02, etc. To add a configuration
descriptor, user must implement a structure similar to CFG01.
The next step is to add the configuration descriptor name, i.e.
cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0]
is a dummy place holder since configuration 0 is the un-configured
state according to the definition in the USB specification.
********************************************************************/
/*********************************************************************
* Descriptor specific type definitions are defined in:
* usb_device.h
*
* Configuration options are defined in:
* usb_config.h
********************************************************************/
#ifndef __USB_DESCRIPTORS_C
#define __USB_DESCRIPTORS_C
/** INCLUDES *******************************************************/
#include "./USB/usb.h"
#include "./USB/usb_function_hid.h"
/** CONSTANTS ******************************************************/
#if defined(__18CXX)
#pragma romdata
#endif
/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
0x12, // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type
0x0200, // USB Spec Release Number in BCD format
0x00, // Class Code
0x00, // Subclass code
0x00, // Protocol code
USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h
0x04D8, // Vendor ID
0x003F, // Product ID: Custom HID device demo
0x0002, // Device release number in BCD format
0x01, // Manufacturer string index
0x02, // Product string index
0x00, // Device serial number string index
0x01 // Number of possible configurations
};
/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
/* Configuration Descriptor */
0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type
0x29,0x00, // Total length of data for this cfg
1, // Number of interfaces in this cfg
1, // Index value of this configuration
0, // Configuration string index
_DEFAULT | _SELF, // Attributes, see usb_device.h
50, // Max power consumption (2X mA)
/* Interface Descriptor */
0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type
0, // Interface Number
0, // Alternate Setting Number
2, // Number of endpoints in this intf
HID_INTF, // Class code
0, // Subclass code
0, // Protocol code
0, // Interface string index
/* HID Class-Specific Descriptor */
0x09,//sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes
DSC_HID, // HID descriptor type
0x11,0x01, // HID Spec Release Number in BCD format (1.11)
0x00, // Country Code (0x00 for Not supported)
HID_NUM_OF_DSC, // Number of class descriptors, see usbcfg.h
DSC_RPT, // Report descriptor type
HID_RPT01_SIZE,0x00,//sizeof(hid_rpt01), // Size of the report descriptor
/* Endpoint Descriptor */
0x07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_IN, //EndpointAddress
_INTERRUPT, //Attributes
0x40,0x00, //size
0x01, //Interval
/* Endpoint Descriptor */
0x07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_OUT, //EndpointAddress
_INTERRUPT, //Attributes
0x40,0x00, //size
0x01 //Interval
};
//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};
//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};
//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'S','i','m','p','l','e',' ','H','I','D',' ',
'D','e','v','i','c','e',' ','D','e','m','o'
}};
//Class specific descriptor - HID
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{
0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1)
0x09, 0x01, // Usage (Vendor Usage 1)
0xA1, 0x01, // Collection (Application)
0x19, 0x01, // Usage Minimum
0x29, 0x40, // Usage Maximum //64 input usages total (0x01 to 0x40)
0x15, 0x01, // Logical Minimum (data bytes in the report may have minimum value = 0x00)
0x25, 0x40, // Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
0x75, 0x08, // Report Size: 8-bit field size
0x95, 0x40, // Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
0x81, 0x00, // Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
0x19, 0x01, // Usage Minimum
0x29, 0x40, // Usage Maximum //64 output usages total (0x01 to 0x40)
0x91, 0x00, // Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
0xC0} // End Collection
};
//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
(ROM BYTE *ROM)&configDescriptor1
};
//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
(ROM BYTE *ROM)&sd000,
(ROM BYTE *ROM)&sd001,
(ROM BYTE *ROM)&sd002
};
/** EOF usb_descriptors.c ***************************************************/
#endif
<実行結果>
PC画面のLED0,LED2、LED3ボタンをクリックして キバン上のLEDを点灯させたあと、キバン上のSW1とSW3をおした時のPCのスクリーンショット画像とキバンの写真です。
ADコンバータで検出された電圧が ダイアログのテキストボックスに小数点以下2桁で3.53[V}と表示されています。
| パソコン画面の ダイアログ |
![]() |
| PIC32MX795F512L キバン上で SW1 とSW3を押したところ |
![]() |
■ PIC32MX795F512L HIDクラス 漢字を含む文字列の送受信(キャラクタ液晶)
PIC32MX795F512Lにキャラクタ液晶を接続した USB通信 送受信の例を紹介します。 → PC側 VC++ ソフト
<試作品仕様>
・PC側からデータをPIC側にUSB HIDクラス通信で送信する。
・送信文字コードはシフトJISを使用する
・PIC側では受信した文字列を液晶上段に、受信データに基づき返信したデータを液晶下段に表示する。
・PC側でも受信したデータをリストボックスに表示する。
・PC側からの送信データ 及びPIC側からの返信データは以下とする。
@ U.K. → London
A America → Washington
B Japan → 0x938c(東)0x8b9e(京)
C 中(0x9286)国 (0x8D91) → 北(0x966B)京(0x8B9E)
D I am a boy. → Pardon ?
<試作品回路図>(→回路図のPDFファイル)

<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

<プログラム例>
//main.c //32MX795
#include "./USB/usb.h"
#include "HardwareProfile.h"
#include "./USB/usb_function_hid.h"
#include "1lcd_lib_C32.h"
//システムクロック80MHz ペリフェラルクロック60MHz
#pragma config UPLLEN = ON // USB PLL Enabled
#pragma config FPLLMUL = MUL_15 // PLL Multiplier
#pragma config UPLLIDIV = DIV_2 // USB PLL Input Divider
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider
#pragma config FPLLODIV = DIV_1 // PLL Output Divider
#pragma config FPBDIV = DIV_1 // Peripheral Clock divisor
#pragma config FWDTEN = OFF // Watchdog Timer
#pragma config WDTPS = PS1 // Watchdog Timer Postscale
#pragma config FCKSM = CSDCMD // Clock Switching & Fail Safe Clock Monitor
#pragma config OSCIOFNC = OFF // CLKO Enable
#pragma config POSCMOD = HS // Primary Oscillator
#pragma config IESO = OFF // Internal/External Switch-over
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (KLO was off)
#pragma config FNOSC = PRIPLL // Oscillator Selection
#pragma config CP = OFF // Code Protect
#pragma config BWP = OFF // Boot Flash Write Protect
#pragma config PWP = OFF // Program Flash Write Protect
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select
#define RX_DATA_BUFFER_ADDRESS
#define TX_DATA_BUFFER_ADDRESS
unsigned char ReceivedDataBuffer[64] RX_DATA_BUFFER_ADDRESS;
unsigned char ToSendDataBuffer[64] TX_DATA_BUFFER_ADDRESS;
unsigned char SendBuf[64];
unsigned char myChr[17]; //文字列部分
char Buf[64]; //文字列のバッファー用レジスタ
unsigned char* str1;
char* str2;
unsigned char Japan[] = "Japan ";
unsigned char UK[] = "U.K. ";
unsigned char America[] = "America ";
//unsigned char Chuugoku[] = "Chuugoku ";
unsigned char Chuugoku[] = {0x92,0x86,0x8D,0x91,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
//中[0x9286] 国[0x8D91]
//char Tokyo[] = "Tokyo \r";
char Tokyo[] = {0x93,0x8C,0x8B,0x9E,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','\r'};
//シフトJIS 東[938C]、京[8B9E]
char Pekin[] = {0x96,0x6B,0x8B,0x9E,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','\r'};
//シフトJIS 北[966B]、京[8B9E]
char London[] = "London \r";
char Washington[] = "Washington \r";
char Pardon[] = "Pardon ? \r";
BOOL blinkStatusValid;
USB_HANDLE USBGenericOutHandle; //送信ハンドル
USB_HANDLE USBGenericInHandle; //受信ハンドル
USB_HANDLE USBOutHandle = 0; //USB handle. Must be initialized to 0 at startup.
USB_HANDLE USBInHandle = 0; //USB handle. Must be initialized to 0 at startup.
void BlinkUSBStatus(void);
void ProcessIO(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);
void delay_us(unsigned int usec) //1μsec遅延関数
{
int count;
count = (int)(Clock/20000000)*usec;
do //実測: at Clock=80000000
{ //delay_us(1000)→1003μsec、 delay_us(100)→102μsec、delay_us(10)→11μsec、delay_us(1)→1.6μsec
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
count--;
}while(count != 0);
}
void delay_ms(unsigned int msec) //1msec遅延関数
{
unsigned int i;
for(i=0; i<msec; i++)
delay_us(1000);
}
int main(void)
{
int i ;
for(i = 0; i < 65; i++)Buf[i] = ' ';
SYSTEMConfigPerformance(60000000); //システム最適化
DDPCONbits.JTAGEN = 0; //JTAG無効化
AD1PCFG = 0xFFFF; //全RBポートデジタルピンとして使用
TRISDbits.TRISD6=1;
TRISDbits.TRISD7=1;
TRISBbits.TRISB15 = 0; //キャラクタ液晶ポート設定
TRISBbits.TRISB14 = 0; //キャラクタ液晶ポート設定
TRISBbits.TRISB13 = 0; //キャラクタ液晶ポート設定
TRISBbits.TRISB12 = 0; //キャラクタ液晶ポート設定
TRISAbits.TRISA9 = 0; //キャラクタ液晶ポート設定
TRISAbits.TRISA10 = 0; //キャラクタ液晶ポート設定
//USB関係
USBDeviceInit();
USBOutHandle = 0;
USBInHandle = 0;
blinkStatusValid = TRUE;
USBDeviceAttach();
lcd_init(); // LCD初期化
lcd_clear(); //クリア
lcd_cmd(0b00001100); // カーソル:OFF ブリンク:OFF
lcd_cmd(0x80); //1目の先頭へ
str1 = &myChr[0];
sprintf(Buf,"Iruma ");//
lcd_str(str1);
lcd_str(Buf); //液晶表示
lcd_cmd(0xC0); //2行目の先頭へ
sprintf(Buf," World !!"); //
lcd_str(Buf); // 開始メッセージ1行目表示
delay_ms(3000);
while(1)
{
// USB接続中なら送受信実行
if((USBDeviceState >= CONFIGURED_STATE)&&(USBSuspendControl!=1))ProcessIO();
}
}
void ProcessIO(void)
{
int i;
if(!HIDRxHandleBusy(USBOutHandle))
{
switch(ReceivedDataBuffer[0]) //コマンドの種類判定
{
//接続確認応答
case 0x30: //
SendBuf[2] = 'O';
SendBuf[3] = 'K';
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64); //PC側に送信
break;
case 0x80: //受信文字列判定 & 対応文字列返信
for(i = 1; i < 17; i++)myChr[i-1] = ReceivedDataBuffer[i];
str1 = &myChr[0];
// str1 = &ReceivedDataBuffer[0];
if(strcmp(str1,Japan) == 0)
{
lcd_cmd(0x80); //1行目へ
sprintf(Buf,"%s",str1);
lcd_str(Buf); //受信データを液晶に表示
lcd_cmd(0xC0); //2行目
sprintf(Buf,"%x%x%x%x",Tokyo[0],Tokyo[1],Tokyo[2],Tokyo[3]);
//sprintf()のバグのため(?)か C18では制御文字の前にffをつける仕様になっているためか
//液晶には ”ff93ff8Cff8Bff9E” と表示される
//シフトJIS 東[938C]、京[8B9E]
lcd_str(Buf); //送信データを液晶に表示
sprintf(Buf,"%c%c%c%c",Tokyo[0],Tokyo[1],Tokyo[2],Tokyo[3]); //送信するときは%cにして送信
}
else if((myChr[0] == Chuugoku[0]) && (myChr[1] == Chuugoku[1]) && (myChr[2] == Chuugoku[2]) && (myChr[3] == Chuugoku[3]) &&
(myChr[4] == Chuugoku[4]) && (myChr[5] == Chuugoku[5]) && (myChr[6] == Chuugoku[6]) && (myChr[7] == Chuugoku[7]) &&
(myChr[8] == Chuugoku[8]) && (myChr[9] == Chuugoku[9]) && (myChr[10] == Chuugoku[10]) && (myChr[11] == Chuugoku[11]) &&
(myChr[12] == Chuugoku[12]) && (myChr[13] == Chuugoku[13]) && (myChr[14] == Chuugoku[14]) && (myChr[15] == Chuugoku[15]))
// else if(strcmp(str1,Chuugoku) == 0) //NG: strcmp( )はASCII文字のみに対応 制御文字には対応していない
{
lcd_cmd(0x80); //1行目へ
sprintf(Buf,"%s",str1);
lcd_str(Buf); //受信データを液晶に表示
lcd_cmd(0xC0); //2行目
sprintf(Buf,"%x%x%x%x",Pekin[0],Pekin[1],Pekin[2],Pekin[3]);
//sprintf()のバグのため(?)か C18では制御文字の前にffをつける仕様になっているためか
//液晶には ”ff93ff8Cff8Bff9E” と表示される
//シフトJIS 東[938C]、京[8B9E]
lcd_str(Buf); //送信データを液晶に表示
sprintf(Buf,"%c%c%c%c",Pekin[0],Pekin[1],Pekin[2],Pekin[3]); //送信するときは%cにして送信
}
else if(strcmp(str1,UK) == 0)
{
str2 = London;
lcd_cmd(0x80); //1行目へ
sprintf(Buf,"%s",str1);
lcd_str(Buf); //受信データを液晶に表示
lcd_cmd(0xC0); //2行目
sprintf(Buf,"%s",str2);
lcd_str(Buf); //送信データを液晶に表示
}
else if(strcmp(str1,America) == 0)
{
str2 = Washington;
lcd_cmd(0x80); //1行目へ
sprintf(Buf,"%s",str1);
lcd_str(Buf); //受信データを液晶に表示
lcd_cmd(0xC0); //2行目
sprintf(Buf,"%s",str2);
lcd_str(Buf); //送信データを液晶に表示
}
else
{
str2 = Pardon;
lcd_cmd(0x80); //1行目へ
sprintf(Buf,"%s",str1);
lcd_str(Buf); //受信データを液晶に表示
lcd_cmd(0xC0); //2行目
sprintf(Buf,"%s",str2);
lcd_str(Buf); //送信データを液晶に表示
}
for(i = 0; i < 18; i++)SendBuf[i] = Buf[i]; //送信データセット
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64); //PC側に送信
break;
}
//次の受信実行
USBOutHandle = HIDRxPacket(HID_EP, (BYTE*)&ReceivedDataBuffer, 64);
}
}
// ******************************************************************************************************
// ************** USB Callback Functions ****************************************************************
// ******************************************************************************************************
void USBCBSuspend(void)
{
}
void USBCBWakeFromSuspend(void)
{
}
void USBCB_SOF_Handler(void)
{
}
void USBCBErrorHandler(void)
{
}
void USBCBCheckOtherReq(void)
{
USBCheckHIDRequest();
}
void USBCBStdSetDscHandler(void)
{
}
void USBCBInitEP(void)
{
//enable the HID endpoint
USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
//Re-arm the OUT endpoint for the next packet
USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}
void USBCBSendResume(void)
{
static WORD delay_count;
if(USBGetRemoteWakeupStatus() == TRUE)
{
if(USBIsBusSuspended() == TRUE)
{
USBMaskInterrupts();
//Clock switch to settings consistent with normal USB operation.
USBCBWakeFromSuspend();
USBSuspendControl = 0;
USBBusIsSuspended = FALSE; //So we don't execute this code again,
//until a new suspend condition is detected.
delay_count = 3600U;
do
{
delay_count--;
}while(delay_count);
//Now drive the resume K-state signalling onto the USB bus.
USBResumeControl = 1; // Start RESUME signaling
delay_count = 1800U; // Set RESUME line for 1-13 ms
do
{
delay_count--;
}while(delay_count);
USBResumeControl = 0; //Finished driving resume signalling
USBUnmaskInterrupts();
}
}
}
BOOL USER_USB_CALLBACK_EVENT_HANDLER(int event, void *pdata, WORD size)
{
switch(event)
{
case EVENT_TRANSFER:
//Add application specific callback task or callback function here if desired.
break;
case EVENT_SOF:
USBCB_SOF_Handler();
break;
case EVENT_SUSPEND:
USBCBSuspend();
break;
case EVENT_RESUME:
USBCBWakeFromSuspend();
break;
case EVENT_CONFIGURED:
USBCBInitEP();
break;
case EVENT_SET_DESCRIPTOR:
USBCBStdSetDscHandler();
break;
case EVENT_EP0_REQUEST:
USBCBCheckOtherReq();
break;
case EVENT_BUS_ERROR:
USBCBErrorHandler();
break;
case EVENT_TRANSFER_TERMINATED:
break;
default:
break;
}
return TRUE;
}
/********************************************************************
FileName: usb_descriptors.c
Dependencies: See INCLUDES section
Processor: PIC18 or PIC24 USB Microcontrollers
Hardware: The code is natively intended to be used on the following
hardware platforms: PICDEM?FS USB Demo Board,
PIC18F87J50 FS USB Plug-In Module, or
Explorer 16 + PIC24 USB PIM. The firmware may be
modified for use on other USB platforms by editing the
HardwareProfile.h file.
Complier: Microchip C18 (for PIC18) or C30 (for PIC24)
Company: Microchip Technology, Inc.
Software License Agreement:
The software supplied herewith by Microchip Technology Incorporated
(the 鼎ompany? for its PICョ Microcontroller is intended and
supplied to you, the Company痴 customer, for use solely and
exclusively on Microchip PIC Microcontroller products. The
software is owned by the Company and/or its supplier, and is
protected under applicable copyright laws. All rights are reserved.
Any use in violation of the foregoing restrictions may subject the
user to criminal sanctions under applicable laws, as well as to
civil liability for the breach of the terms and conditions of this
license.
THIS SOFTWARE IS PROVIDED IN AN 鄭S IS?CONDITION. NO WARRANTIES,
WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*********************************************************************
-usb_descriptors.c-
-------------------------------------------------------------------
Filling in the descriptor values in the usb_descriptors.c file:
-------------------------------------------------------------------
[Device Descriptors]
The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type.
This type is defined in usb_ch9.h Each entry into this structure
needs to be the correct length for the data type of the entry.
[Configuration Descriptors]
The configuration descriptor was changed in v2.x from a structure
to a BYTE array. Given that the configuration is now a byte array
each byte of multi-byte fields must be listed individually. This
means that for fields like the total size of the configuration where
the field is a 16-bit value "64,0," is the correct entry for a
configuration that is only 64 bytes long and not "64," which is one
too few bytes.
The configuration attribute must always have the _DEFAULT
definition at the minimum. Additional options can be ORed
to the _DEFAULT attribute. Available options are _SELF and _RWU.
These definitions are defined in the usb_device.h file. The
_SELF tells the USB host that this device is self-powered. The
_RWU tells the USB host that this device supports Remote Wakeup.
[Endpoint Descriptors]
Like the configuration descriptor, the endpoint descriptors were
changed in v2.x of the stack from a structure to a BYTE array. As
endpoint descriptors also has a field that are multi-byte entities,
please be sure to specify both bytes of the field. For example, for
the endpoint size an endpoint that is 64 bytes needs to have the size
defined as "64,0," instead of "64,"
Take the following example:
// Endpoint Descriptor //
0x07, //the size of this descriptor //
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP02_IN, //EndpointAddress
_INT, //Attributes
0x08,0x00, //size (note: 2 bytes)
0x02, //Interval
The first two parameters are self-explanatory. They specify the
length of this endpoint descriptor (7) and the descriptor type.
The next parameter identifies the endpoint, the definitions are
defined in usb_device.h and has the following naming
convention:
_EP<##>_<dir>
where ## is the endpoint number and dir is the direction of
transfer. The dir has the value of either 'OUT' or 'IN'.
The next parameter identifies the type of the endpoint. Available
options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not
typically used because the default control transfer endpoint is
not defined in the USB descriptors. When _ISO option is used,
addition options can be ORed to _ISO. Example:
_ISO|_AD|_FE
This describes the endpoint as an isochronous pipe with adaptive
and feedback attributes. See usb_device.h and the USB
specification for details. The next parameter defines the size of
the endpoint. The last parameter in the polling interval.
-------------------------------------------------------------------
Adding a USB String
-------------------------------------------------------------------
A string descriptor array should have the following format:
rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={
sizeof(sdxxx),DSC_STR,<text>};
The above structure provides a means for the C compiler to
calculate the length of string descriptor sdxxx, where xxx is the
index number. The first two bytes of the descriptor are descriptor
length and type. The rest <text> are string texts which must be
in the unicode format. The unicode format is achieved by declaring
each character as a word type. The whole text string is declared
as a word array with the number of characters equals to <size>.
<size> has to be manually counted and entered into the array
declaration. Let's study this through an example:
if the string is "USB" , then the string descriptor should be:
(Using index 02)
rom struct{byte bLength;byte bDscType;word string[3];}sd002={
sizeof(sd002),DSC_STR,'U','S','B'};
A USB project may have multiple strings and the firmware supports
the management of multiple strings through a look-up table.
The look-up table is defined as:
rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002};
The above declaration has 3 strings, sd000, sd001, and sd002.
Strings can be removed or added. sd000 is a specialized string
descriptor. It defines the language code, usually this is
US English (0x0409). The index of the string must match the index
position of the USB_SD_Ptr array, &sd000 must be in position
USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on.
The look-up table USB_SD_Ptr is used by the get string handler
function.
-------------------------------------------------------------------
The look-up table scheme also applies to the configuration
descriptor. A USB device may have multiple configuration
descriptors, i.e. CFG01, CFG02, etc. To add a configuration
descriptor, user must implement a structure similar to CFG01.
The next step is to add the configuration descriptor name, i.e.
cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0]
is a dummy place holder since configuration 0 is the un-configured
state according to the definition in the USB specification.
********************************************************************/
/*********************************************************************
* Descriptor specific type definitions are defined in:
* usb_device.h
*
* Configuration options are defined in:
* usb_config.h
********************************************************************/
#ifndef __USB_DESCRIPTORS_C
#define __USB_DESCRIPTORS_C
/** INCLUDES *******************************************************/
#include "./USB/usb.h"
#include "./USB/usb_function_hid.h"
/** CONSTANTS ******************************************************/
#if defined(__18CXX)
#pragma romdata
#endif
/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
0x12, // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type
0x0200, // USB Spec Release Number in BCD format
0x00, // Class Code
0x00, // Subclass code
0x00, // Protocol code
USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h
0x04D8, // Vendor ID
0x003F, // Product ID: Custom HID device demo
0x0002, // Device release number in BCD format
0x01, // Manufacturer string index
0x02, // Product string index
0x00, // Device serial number string index
0x01 // Number of possible configurations
};
/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
/* Configuration Descriptor */
0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type
0x29,0x00, // Total length of data for this cfg
1, // Number of interfaces in this cfg
1, // Index value of this configuration
0, // Configuration string index
_DEFAULT | _SELF, // Attributes, see usb_device.h
50, // Max power consumption (2X mA)
/* Interface Descriptor */
0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type
0, // Interface Number
0, // Alternate Setting Number
2, // Number of endpoints in this intf
HID_INTF, // Class code
0, // Subclass code
0, // Protocol code
0, // Interface string index
/* HID Class-Specific Descriptor */
0x09,//sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes
DSC_HID, // HID descriptor type
0x11,0x01, // HID Spec Release Number in BCD format (1.11)
0x00, // Country Code (0x00 for Not supported)
HID_NUM_OF_DSC, // Number of class descriptors, see usbcfg.h
DSC_RPT, // Report descriptor type
HID_RPT01_SIZE,0x00,//sizeof(hid_rpt01), // Size of the report descriptor
/* Endpoint Descriptor */
0x07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_IN, //EndpointAddress
_INTERRUPT, //Attributes
0x40,0x00, //size
0x01, //Interval
/* Endpoint Descriptor */
0x07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_OUT, //EndpointAddress
_INTERRUPT, //Attributes
0x40,0x00, //size
0x01 //Interval
};
//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};
//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};
//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'S','i','m','p','l','e',' ','H','I','D',' ',
'D','e','v','i','c','e',' ','D','e','m','o'
}};
//Class specific descriptor - HID
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{
0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1)
0x09, 0x01, // Usage (Vendor Usage 1)
0xA1, 0x01, // Collection (Application)
0x19, 0x01, // Usage Minimum
0x29, 0x40, // Usage Maximum //64 input usages total (0x01 to 0x40)
0x15, 0x01, // Logical Minimum (data bytes in the report may have minimum value = 0x00)
0x25, 0x40, // Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
0x75, 0x08, // Report Size: 8-bit field size
0x95, 0x40, // Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
0x81, 0x00, // Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
0x19, 0x01, // Usage Minimum
0x29, 0x40, // Usage Maximum //64 output usages total (0x01 to 0x40)
0x91, 0x00, // Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
0xC0} // End Collection
};
//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
(ROM BYTE *ROM)&configDescriptor1
};
//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
(ROM BYTE *ROM)&sd000,
(ROM BYTE *ROM)&sd001,
(ROM BYTE *ROM)&sd002
};
/** EOF usb_descriptors.c ***************************************************/
#endif
//*************************************************************************
//インクルードファイル 1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//*************************************************************************
#include <proc/p32mx795f512l.h> //PIC32MX460F512L
#define Clock 80000000 // 単位はHzで指定
// LCDポート設定
#define lcd_port_DB7 LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6 LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5 LATBbits.LATB13 //のDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4 LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_rs LATAbits.LATA9 //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定
#define lcd_stb LATAbits.LATA10 //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定
void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);
//**************************************************************************
//インクルードファイル 1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//**************************************************************************
///////////////////////////////////////////////
// 液晶表示器制御ライブラリ for C32コンパイラー
// 内蔵関数は以下
// lcd_init() ----- 初期化
// lcd_cmd(cmd) ----- コマンド出力
// lcd_data(chr) ----- 1文字表示出力
// lcd_clear() ----- 全消去
// lcd_str(str*) ----- 文字列表示
//////////////////////////////////////////////
#include "1lcd_lib_C32.h"
void lcd_delay_us(unsigned int usec) //1μsec遅延関数
{
int count;
count = (int)(Clock/20000000)*usec;
do
{
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
count--;
}while(count != 0);
}
void lcd_delay_ms(unsigned int msec) //1msec遅延関数
{
unsigned int i;
for(i=0; i<msec; i++)
lcd_delay_us(1000);
}
//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
if(code & 0b10000000)lcd_port_DB7 = 1; //LCDのDB7への出力セット
else lcd_port_DB7 = 0;
if(code & 0b01000000)lcd_port_DB6 = 1; //LCDのDB6への出力セット
else lcd_port_DB6 = 0;
if(code & 0b00100000)lcd_port_DB5 = 1; //LCDのDB5への出力セット
else lcd_port_DB5 = 0;
if(code & 0b00010000)lcd_port_DB4 = 1; //LCDのDB4への出力セット
else lcd_port_DB4 = 0;
if (flag == 0)
lcd_rs = 1; // 表示データの場合
else
lcd_rs = 0; // コマンドデータの場合
lcd_delay_us(1); //1μsecウェイト
lcd_stb = 1; // strobe(E) ON (Enable)
lcd_delay_us(1); // 1μsec : strobe信号の幅
lcd_stb = 0; // reset strobe
}
//////// 1文字表示関数
void lcd_data(char asci)
{
lcd_out(asci, 0); // 上位4ビット出力
lcd_out(asci<<4, 0); // 下位4ビット出力
lcd_delay_us(50); //50μsecウェイト
}
/////// コマンド出力関数
void lcd_cmd(char cmd)
{
lcd_out(cmd, 1); // 上位4ビット出力
lcd_out(cmd<<4, 1); // 下位4ビット出力
if((cmd & 0x03) != 0) // clear Homeの場合
lcd_delay_ms(2); // 2msec待ち
else
lcd_delay_us(50); //50μsecウェイト
}
/////// 全消去関数
void lcd_clear(void)
{
lcd_cmd(0x01); // 初期化コマンド出力
}
/////// 文字列出力関数
void lcd_str(char* str)
{
while(*str) //文字列終端の '\0'を検出するまで
{
lcd_data(*str); // 1文字表示
str++; //ポインタをインクリメント
}
}
/////// 初期化関数
void lcd_init(void)
{
lcd_delay_ms(20); //20msecウェイト
lcd_out(0x30, 1); // 8bit mode set
lcd_delay_ms(5); //5msecウェイト
lcd_out(0x30, 1); // 8bit mode set
lcd_delay_ms(1); //1msecウェイト
lcd_out(0x30, 1); // 8bit mode set
lcd_delay_ms(1); //1msecウェイト
lcd_out(0x20, 1); // 4bit mode set
lcd_delay_ms(1); //1msecウェイト
lcd_cmd(0x2E); // DL=0 4bit mode
lcd_cmd(0x08); // display off C=D=B=0
lcd_cmd(0x0D); // display on C=D=1 B=0
lcd_cmd(0x06); // entry I/D=1 S=0
lcd_cmd(0x02); // cursor home
}
<実行結果>
| PIC32MX795F512Lの液晶 上段: PCからの受信文字列 下段: PCへの返信文字列 |
PC画面 | |
| USB接続が 未接続の状態 |
- |
![]() |
| 接続ボタンをクリックして USB接続が 確立した状態 |
- |
![]() |
| コンボボックスから ”U.K.”を選択して送信し、 返信をリストボックスに 受信した状態 |
![]() |
![]() |
| 次に、コンボボックスから ”America”を選択して送信し、 返信をリストボックスに 受信した状態 |
![]() |
![]() |
| 次に、コンボボックスから ”Japan”を選択して送信し、 返信をリストボックスに 受信した状態 |
![]() |
![]() |
| 次に、コンボボックスから ”中国”を選択して送信し、 返信をリストボックスに 受信した状態 |
![]() |
![]() |
| 最後に、コンボボックスから ”I am a boy”を選択して送信し、 返信をリストボックスに 受信した状態 |
![]() |
![]() |
■ PIC32MX795F512L HIDクラス 漢字を含む文字列の送受信(グラフィック液晶)
PIC32MX795F512Lにグラフィック液晶を接続した USB通信 送受信の例を紹介します。 → PC側 VC++ ソフト
<試作品仕様>
・PC側からデータをPIC側にUSB HIDクラス通信で送信する。
・送信文字コードはシフトJISを使用する
・PIC側では受信した文字列を液晶上段に、受信データに基づき返信したデータを液晶下段に表示する。
・PC側でも受信したデータをリストボックスに表示する。
・PC側からの送信データ 及びPIC側からの返信データは以下とする。
@ U.K. → London
A America → Washington
B Japan → 0x938c(東)0x8b9e(京)
C 中(0x9286)国 (0x8D91) → 北(0x966B)京(0x8B9E)
D I am a boy. → Pardon ?
<試作品回路図>(→回路図のPDFファイル)

<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

<プログラム例>
#include "Main.h"
#include "GDD_Screens.h"
//USB関係
#include "./USB/usb.h"
#include "HardwareProfile.h"
#include "./USB/usb_function_hid.h"
#include "1lcd_lib_C32.h"
//システムクロック80MHz ペリフェラルクロック60MHz
#pragma config UPLLEN = ON // USB PLL Enabled
#pragma config FPLLMUL = MUL_15 // PLL Multiplier
#pragma config UPLLIDIV = DIV_2 // USB PLL Input Divider
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider
#pragma config FPLLODIV = DIV_1 // PLL Output Divider
#pragma config FPBDIV = DIV_1 // Peripheral Clock divisor
#pragma config FWDTEN = OFF // Watchdog Timer
#pragma config WDTPS = PS1 // Watchdog Timer Postscale
#pragma config FCKSM = CSDCMD // Clock Switching & Fail Safe Clock Monitor
#pragma config OSCIOFNC = OFF // CLKO Enable
#pragma config POSCMOD = HS // Primary Oscillator
#pragma config IESO = OFF // Internal/External Switch-over
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (KLO was off)
#pragma config FNOSC = PRIPLL // Oscillator Selection
#pragma config CP = OFF // Code Protect
#pragma config BWP = OFF // Boot Flash Write Protect
#pragma config PWP = OFF // Program Flash Write Protect
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select
// Configuration bits
// #pragma config FPLLODIV = DIV_1, FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FWDTEN = OFF, FCKSM = CSECME, FPBDIV = DIV_1
// #pragma config OSCIOFNC = ON, POSCMOD = XT, FSOSCEN = ON, FNOSC = PRIPLL
// #pragma config CP = OFF, BWP = OFF, PWP = OFF
// SPI Device Initialization Function
#if defined (USE_SST25VF016)
#define FlashInit(pInitData) SST25Init((DRV_SPI_INIT_DATA*)pInitData)
#if defined (SPI_CHANNEL_2_ENABLE)
const DRV_SPI_INIT_DATA SPI_Init_Data = {SST25_SPI_CHANNEL, 1, 0, 0, 1, 1, 0};
#endif
#endif
#define RX_DATA_BUFFER_ADDRESS
#define TX_DATA_BUFFER_ADDRESS
unsigned char ReceivedDataBuffer[64] RX_DATA_BUFFER_ADDRESS;
unsigned char ToSendDataBuffer[64] TX_DATA_BUFFER_ADDRESS;
unsigned char SendBuf[64];
unsigned char myChr[17]; //文字列部分
unsigned char tempBuf[1024];
unsigned char* str10;
char Buf[64]; //文字列のバッファー用レジスタ
volatile DWORD tick = 0; // tick counter
unsigned char* str1;
char* str2;
unsigned char Kaigyou[] = "\n";
unsigned char Japan[] = "Japan ";
unsigned char UK[] = "U.K. ";
unsigned char America[] = "America ";
//unsigned char Chuugoku[] = "Chuugoku ";
unsigned char Chuugoku[] = {0x92,0x86,0x8D,0x91,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
//中[0x9286] 国[0x8D91]
char Tokyo_english[] = "Tokyo \r";
char Tokyo[] = {0x93,0x8C,0x8B,0x9E,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','\r'};
//シフトJIS 東[938C]、京[8B9E]
char Pekin[] = {0x96,0x6B,0x8B,0x9E,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','\r'};
//シフトJIS 北[966B]、京[8B9E]
char Pekin_english[] = "Pekin \r";
char London[] = "London \r";
char Washington[] = "Washington \r";
char Pardon[] = "Pardon ? \r";
BOOL blinkStatusValid;
USB_HANDLE USBGenericOutHandle; //送信ハンドル
USB_HANDLE USBGenericInHandle; //受信ハンドル
USB_HANDLE USBOutHandle = 0; //USB handle. Must be initialized to 0 at startup.
USB_HANDLE USBInHandle = 0; //USB handle. Must be initialized to 0 at startup.
// 関数のプロトタイプ宣言
void BlinkUSBStatus(void);
void ProcessIO(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);
void TickInit(void); // starts tick counter
void delay_us(unsigned int usec) //1μsec遅延関数
{
int count;
count = (int)(Clock/20000000)*usec;
do //実測: at Clock=80000000
{ //delay_us(1000)→1003μsec、 delay_us(100)→102μsec、delay_us(10)→11μsec、delay_us(1)→1.6μsec
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
count--;
}while(count != 0);
}
void delay_ms(unsigned int msec) //1msec遅延関数
{
unsigned int i;
for(i=0; i<msec; i++)
delay_us(1000);
}
int main(void)
{
int i ;
for(i = 0; i < 65; i++)Buf[i] = ' ';
SYSTEMConfigPerformance(60000000); //システム最適化
INTEnableSystemMultiVectoredInt(); //ベクタ方式割り込みを許可する
// SYSTEMConfigPerformance(GetSystemClock()); //SYSTEMConfigPerformance(80000000);// システム最適化//キャッシュ・プリフェッチバッファ有効化
DDPCONbits.JTAGEN = 0; //I/OポートとしてRA0、RA1、RA4、RA5をつかう場合、電源投入後DDPCONレジスタのbit3を0に、設定する必要があり;ます。
AD1PCFG =0xFFFF; //★必須 //Bポート:アナログ → デジタル
TRISBbits.TRISB15 = 0; //キャラクタ液晶ポート設定
TRISBbits.TRISB14 = 0; //キャラクタ液晶ポート設定
TRISBbits.TRISB13 = 0; //キャラクタ液晶ポート設定
TRISBbits.TRISB12 = 0; //キャラクタ液晶ポート設定
TRISAbits.TRISA9 = 0; //キャラクタ液晶ポート設定
TRISAbits.TRISA10 = 0; //キャラクタ液晶ポート設定
TRISGbits.TRISG15 = 0; //RG15(1番ピン)ポート LED点灯用
TRISDbits.TRISD2 = 0; //RD2 LED点灯用
TRISDbits.TRISD3 = 0; //RD3 LED点灯用
LATGbits.LATG15 = 1; //LED off
LATDbits.LATD2 = 1; //LED off
LATDbits.LATD3 = 1; //LED off
TRISBbits.TRISB0 = 1; //RB0 in port
TRISBbits.TRISB1 = 1; //RB1 in port
//USB関係
USBDeviceInit();
USBOutHandle = 0;
USBInHandle = 0;
blinkStatusValid = TRUE;
USBDeviceAttach();
lcd_init(); // LCD初期化
lcd_cmd(0b00001100); // カーソル:OFF ブリンク:OFF
lcd_cmd(0x80); //1目の先頭へ
sprintf(Buf,"USB HID");//
lcd_str(Buf); //液晶表示
lcd_cmd(0xC0); //2行目の先頭へ
sprintf(Buf," GDDX LCD Start !!"); //
lcd_str(Buf); // 開始メッセージ1行目表示
DisplayResetDisable(); //Sets RST high
DisplayResetConfig(); //Sets the pin to output
DelayMs(3000); //Wait 500 ms at startup
SetColor(BLACK);
ClearDevice();
GOL_MSG msg; // GOL message structure to interact with GOL
GOLInit(); // Initialize graphics library and create default style scheme for GOL
//SPIフラッシュメモリ初期化 //Set IOs directions for SST25 SPI
//SST25VF016がないと正常に表示されない
//抵抗膜をPIのがADコンバータを使用して、タッチ位置を検出する場合は位置校正記憶のためSST25VF016は必要
SST25_CS_LAT = 1;
SST25_CS_TRIS = 0;
SST25_SCK_TRIS = 0;
SST25_SDO_TRIS = 0;
SST25_SDI_TRIS = 1;
FlashInit(&SPI_Init_Data); // initialize the Flash Memory driver
TouchHardwareInit(); //タッチパネル初期化
TickInit(); //タイマ4 初期化
str10 = &tempBuf[0];
GDDDemoCreateFirstScreen();
while(1)
{
// USB接続中なら送受信実行
if((USBDeviceState >= CONFIGURED_STATE)&&(USBSuspendControl!=1))ProcessIO();
if(GOLDraw()) // Draw GOL object
{
TouchGetMsg(&msg); // Get message from touch screen
GOLMsg(&msg); // Process message
}
}//end while
}
/////////////////////////////////////////////////////////////////////////////
// Function: WORD GOLMsgCallback(WORD objMsg, OBJ_HEADER* pObj, GOL_MSG* pMsg)
// Input: objMsg - translated message for the object,
// pObj - pointer to the object,
// pMsg - pointer to the non-translated, raw GOL message
// Output: if the function returns non-zero the message will be processed by default
// Overview: it's a user defined function. GOLMsg() function calls it each
// time the valid message for the object received
/////////////////////////////////////////////////////////////////////////////
WORD GOLMsgCallback(WORD objMsg, OBJ_HEADER *pObj, GOL_MSG *pMsg)
{
WORD objectID;
objectID = GetObjID(pObj);
GDDDemoGOLMsgCallback(objMsg, pObj, pMsg);
// Add additional code here...
return (1);
}
/////////////////////////////////////////////////////////////////////////////
// Function: WORD GOLDrawCallback()
// Output: if the function returns non-zero the draw control will be passed to GOL
// Overview: it's a user defined function. GOLDraw() function calls it each
// time when GOL objects drawing is completed. User drawing should be done here.
// GOL will not change color, line type and clipping region settings while
// this function returns zero.
/////////////////////////////////////////////////////////////////////////////
WORD GOLDrawCallback(void)
{
GDDDemoGOLDrawCallback();
// Add additional code here...
return (1);
}
void __ISR(_TIMER_4_VECTOR, ipl1) _T4Interrupt(void) //タイマ4割り込み //100msec毎
{
// LATGbits.LATG15 = 0; //割り込み時間(実測):3msec
tick++;
TMR4 = 0;
mT4ClearIntFlag(); // Clear flag
TouchDetectPosition();
/*
lcd_clear(); // 全消去
lcd_cmd(0x80); //1行目の先頭へ
sprintf(Buf,"X = %d",TouchGetX());//タッチX座標表示
lcd_str(Buf); //液晶表示
lcd_cmd(0xC0); //2行目の先頭へ
sprintf(Buf,"Y = %d",TouchGetY()); //タッチY座標表示
lcd_str(Buf); // 開始メッセージ1行目表示
*/
// LATGbits.LATG15 = 1;
}
//---------------------------------------------------------------------------------
#define SAMPLE_PERIOD 500 // us
#define TICK_PERIOD (GetPeripheralClock() * SAMPLE_PERIOD) / 4000000
//TICK_PERIOD = 80000000 * 500 / 4000000 = 80* 500 / 4 = 20*500 = 10000
void TickInit(void) //タイマ4初期化
{
OpenTimer4(T4_ON | T4_PS_1_256, 31249); //1000/80000000*256*31249 =99.9968 msec
// OpenTimer4(T4_ON | T4_PS_1_8, 10000); //2msec
// OpenTimer4(T4_ON | T4_PS_1_8, TICK_PERIOD); //実測値:35μsec //オーバーフローエラー発生
ConfigIntTimer4(T4_INT_ON | T4_INT_PRIOR_1);
}
void ProcessIO(void)
{
int i;
if(!HIDRxHandleBusy(USBOutHandle))
{
switch(ReceivedDataBuffer[0]) //コマンドの種類判定
{
//接続確認応答
case 0x30: //
SendBuf[2] = 'O';
SendBuf[3] = 'K';
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64); //PC側に送信
break;
case 0x80: //受信文字列判定 & 対応文字列返信
for(i = 1; i < 17; i++)myChr[i-1] = ReceivedDataBuffer[i];
str1 = &myChr[0];
// str1 = &ReceivedDataBuffer[0];
if(strcmp(str1,Japan) == 0)
{
lcd_cmd(0x80); //1行目へ
sprintf(Buf,"%s",str1);
lcd_str(Buf); //受信データを液晶に表示
lcd_cmd(0xC0); //2行目
sprintf(Buf,"%x%x%x%x",Tokyo[0],Tokyo[1],Tokyo[2],Tokyo[3]);
//sprintf()のバグのため(?)か C18では制御文字の前にffをつける仕様になっているためか
//液晶には ”ff93ff8Cff8Bff9E” と表示される
//シフトJIS 東[938C]、京[8B9E]
lcd_str(Buf); //送信データを液晶に表示
sprintf(Buf,"%c%c%c%c",Tokyo[0],Tokyo[1],Tokyo[2],Tokyo[3]); //送信するときは%cにして送信
str2 = Tokyo_english;
}
else if((myChr[0] == Chuugoku[0]) && (myChr[1] == Chuugoku[1]) && (myChr[2] == Chuugoku[2]) && (myChr[3] == Chuugoku[3]) &&
(myChr[4] == Chuugoku[4]) && (myChr[5] == Chuugoku[5]) && (myChr[6] == Chuugoku[6]) && (myChr[7] == Chuugoku[7]) &&
(myChr[8] == Chuugoku[8]) && (myChr[9] == Chuugoku[9]) && (myChr[10] == Chuugoku[10]) && (myChr[11] == Chuugoku[11]) &&
(myChr[12] == Chuugoku[12]) && (myChr[13] == Chuugoku[13]) && (myChr[14] == Chuugoku[14]) && (myChr[15] == Chuugoku[15]))
// else if(strcmp(str1,Chuugoku) == 0) //NG: strcmp( )はASCII文字のみに対応 制御文字には対応していない
{
lcd_cmd(0x80); //1行目へ
sprintf(Buf,"%s",str1);
lcd_str(Buf); //受信データを液晶に表示
lcd_cmd(0xC0); //2行目
sprintf(Buf,"%x%x%x%x",Pekin[0],Pekin[1],Pekin[2],Pekin[3]);
//sprintf()のバグのため(?)か C18では制御文字の前にffをつける仕様になっているためか
//液晶には ”ff93ff8Cff8Bff9E” と表示される
//シフトJIS 東[938C]、京[8B9E]
lcd_str(Buf); //送信データを液晶に表示
sprintf(Buf,"%c%c%c%c",Pekin[0],Pekin[1],Pekin[2],Pekin[3]); //送信するときは%cにして送信
str2 = Pekin_english;
}
else if(strcmp(str1,UK) == 0)
{
str2 = London;
lcd_cmd(0x80); //1行目へ
sprintf(Buf,"%s",str1);
lcd_str(Buf); //受信データを液晶に表示
lcd_cmd(0xC0); //2行目
sprintf(Buf,"%s",str2);
lcd_str(Buf); //送信データを液晶に表示
}
else if(strcmp(str1,America) == 0)
{
str2 = Washington;
lcd_cmd(0x80); //1行目へ
sprintf(Buf,"%s",str1);
lcd_str(Buf); //受信データを液晶に表示
lcd_cmd(0xC0); //2行目
sprintf(Buf,"%s",str2);
lcd_str(Buf); //送信データを液晶に表示
}
else
{
str2 = Pardon;
lcd_cmd(0x80); //1行目へ
sprintf(Buf,"%s",str1);
lcd_str(Buf); //受信データを液晶に表示
lcd_cmd(0xC0); //2行目
sprintf(Buf,"%s",str2);
lcd_str(Buf); //送信データを液晶に表示
}
//グラフィック液晶のStatic Text Widgetに表示
STATICTEXT *pSTE_1 = (STATICTEXT*)GOLFindObject(STE_1); //エディットボックスのオブジェクト検出
pSTE_1->hdr.state = ST_DRAW; //再描画により文字は左アラインにリセットされる
strncat(str10,str2,16); //文字追加
strncat(str10,Kaigyou,16); //改行
StSetText((STATICTEXT*)pSTE_1, str10); //
SetState(pSTE_1, ST_DRAW);
for(i = 0; i < 18; i++)SendBuf[i] = Buf[i]; //送信データセット
if(!HIDTxHandleBusy(USBInHandle))
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&SendBuf[0],64); //PC側に送信
break;
}
//次の受信実行
USBOutHandle = HIDRxPacket(HID_EP, (BYTE*)&ReceivedDataBuffer, 64);
}
}
// ******************************************************************************************************
// ************** USB Callback Functions ****************************************************************
// ******************************************************************************************************
void USBCBSuspend(void)
{
}
void USBCBWakeFromSuspend(void)
{
}
void USBCB_SOF_Handler(void)
{
}
void USBCBErrorHandler(void)
{
}
void USBCBCheckOtherReq(void)
{
USBCheckHIDRequest();
}
void USBCBStdSetDscHandler(void)
{
}
void USBCBInitEP(void)
{
//enable the HID endpoint
USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
//Re-arm the OUT endpoint for the next packet
USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}
void USBCBSendResume(void)
{
static WORD delay_count;
if(USBGetRemoteWakeupStatus() == TRUE)
{
if(USBIsBusSuspended() == TRUE)
{
USBMaskInterrupts();
//Clock switch to settings consistent with normal USB operation.
USBCBWakeFromSuspend();
USBSuspendControl = 0;
USBBusIsSuspended = FALSE; //So we don't execute this code again,
//until a new suspend condition is detected.
delay_count = 3600U;
do
{
delay_count--;
}while(delay_count);
//Now drive the resume K-state signalling onto the USB bus.
USBResumeControl = 1; // Start RESUME signaling
delay_count = 1800U; // Set RESUME line for 1-13 ms
do
{
delay_count--;
}while(delay_count);
USBResumeControl = 0; //Finished driving resume signalling
USBUnmaskInterrupts();
}
}
}
BOOL USER_USB_CALLBACK_EVENT_HANDLER(int event, void *pdata, WORD size)
{
switch(event)
{
case EVENT_TRANSFER:
//Add application specific callback task or callback function here if desired.
break;
case EVENT_SOF:
USBCB_SOF_Handler();
break;
case EVENT_SUSPEND:
USBCBSuspend();
break;
case EVENT_RESUME:
USBCBWakeFromSuspend();
break;
case EVENT_CONFIGURED:
USBCBInitEP();
break;
case EVENT_SET_DESCRIPTOR:
USBCBStdSetDscHandler();
break;
case EVENT_EP0_REQUEST:
USBCBCheckOtherReq();
break;
case EVENT_BUS_ERROR:
USBCBErrorHandler();
break;
case EVENT_TRANSFER_TERMINATED:
break;
default:
break;
}
return TRUE;
}
//------------------------------------------------------------------------------
//usb_descriptors.c
/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
0x12, // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type
0x0200, // USB Spec Release Number in BCD format
0x00, // Class Code
0x00, // Subclass code
0x00, // Protocol code
USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h
0x04D8, // Vendor ID
0x003F, // Product ID: Custom HID device demo
0x0002, // Device release number in BCD format
0x01, // Manufacturer string index
0x02, // Product string index
0x00, // Device serial number string index
0x01 // Number of possible configurations
};
/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
/* Configuration Descriptor */
0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type
0x29,0x00, // Total length of data for this cfg
1, // Number of interfaces in this cfg
1, // Index value of this configuration
0, // Configuration string index
_DEFAULT | _SELF, // Attributes, see usb_device.h
50, // Max power consumption (2X mA)
/* Interface Descriptor */
0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type
0, // Interface Number
0, // Alternate Setting Number
2, // Number of endpoints in this intf
HID_INTF, // Class code
0, // Subclass code
0, // Protocol code
0, // Interface string index
/* HID Class-Specific Descriptor */
0x09,//sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes
DSC_HID, // HID descriptor type
0x11,0x01, // HID Spec Release Number in BCD format (1.11)
0x00, // Country Code (0x00 for Not supported)
HID_NUM_OF_DSC, // Number of class descriptors, see usbcfg.h
DSC_RPT, // Report descriptor type
HID_RPT01_SIZE,0x00,//sizeof(hid_rpt01), // Size of the report descriptor
/* Endpoint Descriptor */
0x07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_IN, //EndpointAddress
_INTERRUPT, //Attributes
0x40,0x00, //size
0x01, //Interval
/* Endpoint Descriptor */
0x07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
HID_EP | _EP_OUT, //EndpointAddress
_INTERRUPT, //Attributes
0x40,0x00, //size
0x01 //Interval
};
//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409
}};
//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[25];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'M','i','c','r','o','c','h','i','p',' ',
'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'
}};
//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[22];}sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
{'S','i','m','p','l','e',' ','H','I','D',' ',
'D','e','v','i','c','e',' ','D','e','m','o'
}};
//Class specific descriptor - HID
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{
0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1)
0x09, 0x01, // Usage (Vendor Usage 1)
0xA1, 0x01, // Collection (Application)
0x19, 0x01, // Usage Minimum
0x29, 0x40, // Usage Maximum //64 input usages total (0x01 to 0x40)
0x15, 0x01, // Logical Minimum (data bytes in the report may have minimum value = 0x00)
0x25, 0x40, // Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
0x75, 0x08, // Report Size: 8-bit field size
0x95, 0x40, // Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
0x81, 0x00, // Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
0x19, 0x01, // Usage Minimum
0x29, 0x40, // Usage Maximum //64 output usages total (0x01 to 0x40)
0x91, 0x00, // Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
0xC0} // End Collection
};
//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
(ROM BYTE *ROM)&configDescriptor1
};
//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
(ROM BYTE *ROM)&sd000,
(ROM BYTE *ROM)&sd001,
(ROM BYTE *ROM)&sd002
};
/** EOF usb_descriptors.c ***************************************************/
#endif
//*************************************************************************
//インクルードファイル 1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//*************************************************************************
#include <proc/p32mx795f512l.h> //PIC32MX460F512L
#define Clock 80000000 // 単位はHzで指定
// LCDポート設定
#define lcd_port_DB7 LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6 LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5 LATBbits.LATB13 //のDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4 LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_rs LATAbits.LATA9 //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定
#define lcd_stb LATAbits.LATA10 //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定
void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);
//**************************************************************************
//インクルードファイル 1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//**************************************************************************
///////////////////////////////////////////////
// 液晶表示器制御ライブラリ for C32コンパイラー
// 内蔵関数は以下
// lcd_init() ----- 初期化
// lcd_cmd(cmd) ----- コマンド出力
// lcd_data(chr) ----- 1文字表示出力
// lcd_clear() ----- 全消去
// lcd_str(str*) ----- 文字列表示
//////////////////////////////////////////////
#include "1lcd_lib_C32.h"
void lcd_delay_us(unsigned int usec) //1μsec遅延関数
{
int count;
count = (int)(Clock/20000000)*usec;
do
{
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
count--;
}while(count != 0);
}
void lcd_delay_ms(unsigned int msec) //1msec遅延関数
{
unsigned int i;
for(i=0; i<msec; i++)
lcd_delay_us(1000);
}
//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
if(code & 0b10000000)lcd_port_DB7 = 1; //LCDのDB7への出力セット
else lcd_port_DB7 = 0;
if(code & 0b01000000)lcd_port_DB6 = 1; //LCDのDB6への出力セット
else lcd_port_DB6 = 0;
if(code & 0b00100000)lcd_port_DB5 = 1; //LCDのDB5への出力セット
else lcd_port_DB5 = 0;
if(code & 0b00010000)lcd_port_DB4 = 1; //LCDのDB4への出力セット
else lcd_port_DB4 = 0;
if (flag == 0)
lcd_rs = 1; // 表示データの場合
else
lcd_rs = 0; // コマンドデータの場合
lcd_delay_us(1); //1μsecウェイト
lcd_stb = 1; // strobe(E) ON (Enable)
lcd_delay_us(1); // 1μsec : strobe信号の幅
lcd_stb = 0; // reset strobe
}
//////// 1文字表示関数
void lcd_data(char asci)
{
lcd_out(asci, 0); // 上位4ビット出力
lcd_out(asci<<4, 0); // 下位4ビット出力
lcd_delay_us(50); //50μsecウェイト
}
/////// コマンド出力関数
void lcd_cmd(char cmd)
{
lcd_out(cmd, 1); // 上位4ビット出力
lcd_out(cmd<<4, 1); // 下位4ビット出力
if((cmd & 0x03) != 0) // clear Homeの場合
lcd_delay_ms(2); // 2msec待ち
else
lcd_delay_us(50); //50μsecウェイト
}
/////// 全消去関数
void lcd_clear(void)
{
lcd_cmd(0x01); // 初期化コマンド出力
}
/////// 文字列出力関数
void lcd_str(char* str)
{
while(*str) //文字列終端の '\0'を検出するまで
{
lcd_data(*str); // 1文字表示
str++; //ポインタをインクリメント
}
}
/////// 初期化関数
void lcd_init(void)
{
lcd_delay_ms(20); //20msecウェイト
lcd_out(0x30, 1); // 8bit mode set
lcd_delay_ms(5); //5msecウェイト
lcd_out(0x30, 1); // 8bit mode set
lcd_delay_ms(1); //1msecウェイト
lcd_out(0x30, 1); // 8bit mode set
lcd_delay_ms(1); //1msecウェイト
lcd_out(0x20, 1); // 4bit mode set
lcd_delay_ms(1); //1msecウェイト
lcd_cmd(0x2E); // DL=0 4bit mode
lcd_cmd(0x08); // display off C=D=B=0
lcd_cmd(0x0D); // display on C=D=1 B=0
lcd_cmd(0x06); // entry I/D=1 S=0
lcd_cmd(0x02); // cursor home
}
}
//その他 FAT、グラフィックライブラリ関連のインクルードファイルは下記にあります。 //マイクロチップのライブラリダウンロードページ: Microchip Libraries for Applications 私がつかったバージョンは \microchip_solutions_v2013-02-15 です。 //GDDX関連のファイルは Microchip Graphics Display Designer X からダウンロードできます。 私がつかったバージョンは GDDX v.1.10 です //グラフィック液晶INT035TFTの関連情報は Displaytechのホームページ 及び DisplaytechのForum にあります。
<実行結果>
| PIC32MX795F512Lのグラフィック液晶 上段: PCからの受信文字列 下段: PCへの返信文字列 |
PC画面 | |
| USB接続が 未接続の状態 |
- |
![]() |
| 接続ボタンをクリックして USB接続が 確立した状態 |
- |
![]() |
| コンボボックスから ”U.K.”を選択して送信し、 返信をリストボックスに 受信した状態 |
![]() |
![]() |
| 次に、コンボボックスから ”America”を選択して送信し、 返信をリストボックスに 受信した状態 |
![]() |
![]() |
| 次に、コンボボックスから ”Japan”を選択して送信し、 返信をリストボックスに 受信した状態 |
![]() |
![]() |
| 次に、コンボボックスから ”中国”を選択して送信し、 返信をリストボックスに 受信した状態 |
![]() |
![]() |
| 最後に、コンボボックスから ”I am a boy”を選択して送信し、 返信をリストボックスに 受信した状態 |
![]() |
![]() |
■ PIC32MX795F512L <HIDクラス・ホストモード> グラフィック液晶 ASSCII文字簡易エディタ
グラフィック液晶付PIC32MX795F512Lに USBコネクタの市販キーボードを接続した場合の 簡単なエディタを作ったので紹介します。
<試作品仕様>
・PIC32MX795F512Lにグラフィック液晶を8080 16ビットパラレルで接続する
・市販の日本語109キーボードを接続して キーボードから打鍵して文字と記号をグラフィック液晶に表示する
・グラフィックでの文字にはマイクロチップのGDDXのStatic Text ウィジェットを用いる
・表示の他に エンターキーでの改行 及びバックスペースキーとデリートキーでの文字消去ができること
<試作品回路図>(→回路図のPDFファイル)
<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

<プログラム例>
//Main( ).c
#include "Main.h"
#include "GDD_Screens.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "GenericTypeDefs.h"
#include "HardwareProfile.h"
#include "usb_config.h"
#include "USB/usb.h"
#include "USB/usb_host_hid_parser.h"
#include "USB/usb_host_hid.h"
#include "1lcd_lib_C32.h"
#define STOP_TIMER_IN_IDLE_MODE 0x2000
#define TIMER_SOURCE_INTERNAL 0x0000
#define TIMER_ON 0x8000
#define GATED_TIME_DISABLED 0x0000
#define TIMER_16BIT_MODE 0x0000
#define TIMER_PRESCALER_1 0x0000
#define TIMER_PRESCALER_8 0x0010
#define TIMER_PRESCALER_64 0x0020
#define TIMER_PRESCALER_256 0x0030
#define TIMER_INTERRUPT_PRIORITY 0x0001
// Configuration bits
#pragma config FPLLODIV = DIV_1, FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FWDTEN = OFF, FCKSM = CSECME, FPBDIV = DIV_1
#pragma config OSCIOFNC = ON, POSCMOD = XT, FSOSCEN = ON, FNOSC = PRIPLL
#pragma config CP = OFF, BWP = OFF, PWP = OFF
#pragma config UPLLEN = ON // USB PLL Enabled
#pragma config UPLLIDIV = DIV_2 // USB PLL Input Divider
typedef enum _APP_STATE
{
DEVICE_NOT_CONNECTED,
DEVICE_CONNECTED, /* Device Enumerated - Report Descriptor Parsed */
READY_TO_TX_RX_REPORT,
GET_INPUT_REPORT, /* perform operation on received report */
INPUT_REPORT_PENDING,
SEND_OUTPUT_REPORT, /* Not needed in case of mouse */
OUTPUT_REPORT_PENDING,
ERROR_REPORTED
} APP_STATE;
typedef struct _HID_REPORT_BUFFER
{
WORD Report_ID;
WORD ReportSize;
BYTE* ReportData;
WORD ReportPollRate;
} HID_REPORT_BUFFER;
typedef struct _HID_LED_REPORT_BUFFER
{
BYTE NUM_LOCK : 1;
BYTE CAPS_LOCK : 1;
BYTE SCROLL_LOCK : 1;
BYTE UNUSED : 5;
} HID_LED_REPORT_BUFFER;
#define MAX_ALLOWED_CURRENT (500) // Maximum power we can supply in mA
#define MINIMUM_POLL_INTERVAL (0x0A) // Minimum Polling rate for HID reports is 10ms
#define USAGE_PAGE_LEDS (0x08)
#define USAGE_PAGE_KEY_CODES (0x07)
#define USAGE_MIN_MODIFIER_KEY (0xE0)
#define USAGE_MAX_MODIFIER_KEY (0xE7)
#define USAGE_MIN_NORMAL_KEY (0x00)
#define USAGE_MAX_NORMAL_KEY (0xFF)
/* Array index for modifier keys */
#define MODIFIER_LEFT_CONTROL (0)
#define MODIFIER_LEFT_SHIFT (1)
#define MODIFIER_LEFT_ALT (2)
#define MODIFIER_LEFT_GUI (3)
#define MODIFIER_RIGHT_CONTROL (4)
#define MODIFIER_RIGHT_SHIFT (5)
#define MODIFIER_RIGHT_ALT (6)
#define MODIFIER_RIGHT_GUI (7)
#define HID_CAPS_LOCK_VAL (0x39)
#define HID_NUM_LOCK_VAL (0x53)
#define MAX_ERROR_COUNTER (10)
#define LCD_LINE_ONE (1)
#define LCD_LINE_TWO (2)
// macros to identify special charaters(other than Digits and Alphabets)
#define Symbol_Exclamation (0x1E)
#define Symbol_AT (0x1F)
#define Symbol_Pound (0x20)
#define Symbol_Dollar (0x21)
#define Symbol_Percentage (0x22)
#define Symbol_Cap (0x23)
#define Symbol_AND (0x24)
#define Symbol_Star (0x25)
#define Symbol_NormalBracketOpen (0x26)
#define Symbol_NormalBracketClose (0x27)
#define Symbol_Return (0x28)
#define Symbol_Escape (0x29)
#define Symbol_Backspace (0x2A)
#define Symbol_Tab (0x2B)
#define Symbol_Space (0x2C)
#define Symbol_HyphenUnderscore (0x2D)
#define Symbol_EqualAdd (0x2E)
#define Symbol_BracketOpen (0x2F)
#define Symbol_BracketClose (0x30)
#define Symbol_BackslashOR (0x31)
#define Symbol_SemiColon (0x33)
#define Symbol_InvertedComma (0x34)
#define Symbol_Tilde (0x35) //109キーボードの漢字・全角/半角キーとバティングしている
#define Symbol_CommaLessThan (0x36)
#define Symbol_PeriodGreaterThan (0x37)
#define Symbol_FrontSlashQuestion (0x38)
#define Symbol_Kanji (0x35)
#define Symbol_ScrLK (0x47)
#define Symbol_PrintScr (0x46)
#define Symbol_Delete (0x4C)
#define Symbol_PauseBreak (0x48)
//
APP_STATE App_State_Keyboard = DEVICE_NOT_CONNECTED;
HID_DATA_DETAILS Appl_LED_Indicator;
HID_DATA_DETAILS Appl_ModifierKeysDetails;
HID_DATA_DETAILS Appl_NormalKeysDetails;
HID_USER_DATA_SIZE Appl_BufferModifierKeys[8];
HID_USER_DATA_SIZE Appl_BufferNormalKeys[6];
HID_USER_DATA_SIZE Appl_ShadowBuffer1[6];
HID_REPORT_BUFFER Appl_raw_report_buffer;
HID_LED_REPORT_BUFFER Appl_led_report_buffer;
BYTE ErrorDriver;
BYTE ErrorCounter;
BYTE NumOfBytesRcvd;
BOOL ReportBufferUpdated;
BOOL LED_Key_Pressed = FALSE;
BOOL DisplayConnectOnce = FALSE;
BOOL DisplayDeatachOnce = FALSE;
BYTE CAPS_Lock_Pressed = 0;
BYTE NUM_Lock_Pressed = 0;
BYTE HeldKeyCount = 0;
BYTE HeldKey;
BYTE currCharPos;
BYTE FirstKeyPressed ;
// SPI Device Initialization Function
#if defined (USE_SST25VF016)
#define FlashInit(pInitData) SST25Init((DRV_SPI_INIT_DATA*)pInitData)
#if defined (SPI_CHANNEL_2_ENABLE)
const DRV_SPI_INIT_DATA SPI_Init_Data = {SST25_SPI_CHANNEL, 1, 0, 0, 1, 1, 0};
#endif
#endif
BYTE App_HID2ASCII(BYTE a); //convert USB HID code (buffer[2 to 7]) to ASCII code
void AppInitialize(void);
BOOL AppGetParsedReportDetails(void);
void App_Detect_Device(void);
void App_ProcessInputReport(void);
void App_PrepareOutputReport(void);
void InitializeTimer(void);
void App_Clear_Data_Buffer(void);
BOOL App_CompareKeyPressedPrevBuf(BYTE data);
void App_CopyToShadowBuffer(void);
BOOL USB_HID_DataCollectionHandler(void);
void LCD_Display_Routine(BYTE data, BYTE HIDData);
void ProcessIO(void);
char Buf[65]; //文字列のバッファー用レジスタ
volatile DWORD tick = 0; // tick counter
int myMode = 0;
int GLcdLineNum = 0; //グラフィック液晶の行数
unsigned char Kaigyou[] = "\n";
unsigned char tempBuf[1024];
unsigned char* myAllChar;
unsigned char tempBuf2[1024];
unsigned char* str20;
int myLineNum = 0; //エディタの書込み行番号(0-12)
int myColumnNum = -1; //表示する文字の列番号
int myCharPos = 0; //
int myColumnNum0 = 30;
// 関数のプロトタイプ宣言
void TickInit(void); // starts tick counter
//------------------------------------------------------------------------------
void delay_us(unsigned int usec) //1μsec遅延関数
{
int count;
count = (int)(Clock/20000000)*usec;
do //実測: at Clock=80000000
{ //delay_us(1000)→1003μsec、 delay_us(100)→102μsec、delay_us(10)→11μsec、delay_us(1)→1.6μsec
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
count--;
}while(count != 0);
}
//------------------------------------------------------------------------------
void delay_ms(unsigned int msec) //1msec遅延関数
{
unsigned int i;
for(i=0; i<msec; i++)
delay_us(1000);
}
int main(void)
{
INTEnableSystemMultiVectoredInt(); //ベクタ方式割り込みを許可する
SYSTEMConfigPerformance(GetSystemClock()); //SYSTEMConfigPerformance(80000000);// システム最適化//キャッシュ・プリフェッチバッファ有効化
DDPCONbits.JTAGEN = 0; //I/OポートとしてRA0、RA1、RA4、RA5をつかう場合、電源投入後DDPCONレジスタのbit3を0に、設定する必要があり;ます。
SYSTEMConfigWaitStatesAndPB( GetSystemClock() ); //フラッシュメモリとPBCLKデバイダを指定したクロックで最適な状態に自動的に設定
CheKseg0CacheOn(); // Enable the cache for the best performance
AD1PCFG =0xFFFF; //★必須 //Bポート:アナログ → デジタル
TRISBbits.TRISB15 = 0; //キャラクタ液晶ポート設定
TRISBbits.TRISB14 = 0; //キャラクタ液晶ポート設定
TRISBbits.TRISB13 = 0; //キャラクタ液晶ポート設定
TRISBbits.TRISB12 = 0; //キャラクタ液晶ポート設定
TRISAbits.TRISA9 = 0; //キャラクタ液晶ポート設定
TRISAbits.TRISA10 = 0; //キャラクタ液晶ポート設定
TRISGbits.TRISG15 = 0; //RG15(1番ピン)ポート LED点灯用
TRISDbits.TRISD2 = 0; //RD2 LED点灯用
TRISDbits.TRISD3 = 0; //RD3 LED点灯用
LATGbits.LATG15 = 1; //LED off
LATDbits.LATD2 = 1; //LED off
LATDbits.LATD3 = 1; //LED off
TRISBbits.TRISB0 = 1; //RB0 in port
TRISBbits.TRISB1 = 1; //RB1 in port
lcd_init(); // LCD初期化
lcd_cmd(0b00001100); // カーソル:OFF ブリンク:OFF
lcd_clear();
lcd_cmd(0x80); //1目の先頭へ
sprintf(Buf,"USB & Touchi");//
lcd_str(Buf); //液晶表示
lcd_cmd(0xC0); //2行目の先頭へ
sprintf(Buf," Start !!"); //
lcd_str(Buf); // 開始メッセージ1行目表示
DisplayResetDisable(); //Sets RST high
DisplayResetConfig(); //Sets the pin to output
DelayMs(3000); //Wait 500 ms at startup
SetColor(BLACK);
ClearDevice();
GOL_MSG msg; // GOL message structure to interact with GOL
GOLInit(); // Initialize graphics library and create default style scheme for GOL
//SPIフラッシュメモリ初期化 //Set IOs directions for SST25 SPI
//SST25VF016がないと正常に表示されない
//抵抗膜をPIのがADコンバータを使用して、タッチ位置を検出する場合は位置校正記憶のためSST25VF016は必要
SST25_CS_LAT = 1;
SST25_CS_TRIS = 0;
SST25_SCK_TRIS = 0;
SST25_SDO_TRIS = 0;
SST25_SDI_TRIS = 1;
FlashInit(&SPI_Init_Data); // initialize the Flash Memory driver
USBInitialize(0); //USBイニシャライズ
TouchHardwareInit(); //タッチパネル初期化
TickInit(); //タイマ4 初期化
GDDDemoCreateFirstScreen();
myAllChar = &tempBuf[0];
str20 = &tempBuf2[0];
while(1)
{
USBTasks();
ProcessIO();
if(GOLDraw()) // Draw GOL object
{
TouchGetMsg(&msg); // Get message from touch screen
GOLMsg(&msg); // Process message
}
}//end while
}
/////////////////////////////////////////////////////////////////////////////
// Function: WORD GOLMsgCallback(WORD objMsg, OBJ_HEADER* pObj, GOL_MSG* pMsg)
// Input: objMsg - translated message for the object,
// pObj - pointer to the object,
// pMsg - pointer to the non-translated, raw GOL message
// Output: if the function returns non-zero the message will be processed by default
// Overview: it's a user defined function. GOLMsg() function calls it each
// time the valid message for the object received
/////////////////////////////////////////////////////////////////////////////
WORD GOLMsgCallback(WORD objMsg, OBJ_HEADER *pObj, GOL_MSG *pMsg)
{
WORD objectID;
objectID = GetObjID(pObj);
GDDDemoGOLMsgCallback(objMsg, pObj, pMsg);
// Add additional code here...
return (1);
}
/////////////////////////////////////////////////////////////////////////////
// Function: WORD GOLDrawCallback()
// Output: if the function returns non-zero the draw control will be passed to GOL
// Overview: it's a user defined function. GOLDraw() function calls it each
// time when GOL objects drawing is completed. User drawing should be done here.
// GOL will not change color, line type and clipping region settings while
// this function returns zero.
/////////////////////////////////////////////////////////////////////////////
WORD GOLDrawCallback(void)
{
GDDDemoGOLDrawCallback();
// Add additional code here...
return (1);
}
void __ISR(_TIMER_4_VECTOR, ipl1) _T4Interrupt(void) //タイマ4割り込み //100msec毎
{
// LATGbits.LATG15 = 0; //割り込み時間(実測):3msec
tick++;
TMR4 = 0;
mT4ClearIntFlag(); // Clear flag
TouchDetectPosition();
/*
lcd_clear(); // 全消去
lcd_cmd(0x80); //1行目の先頭へ
sprintf(Buf,"X = %d",TouchGetX());//タッチX座標表示
lcd_str(Buf); //液晶表示
lcd_cmd(0xC0); //2行目の先頭へ
sprintf(Buf,"Y = %d",TouchGetY()); //タッチY座標表示
lcd_str(Buf); // 開始メッセージ1行目表示
*/
// LATGbits.LATG15 = 1;
}
//---------------------------------------------------------------------------------
#define SAMPLE_PERIOD 500 // us
#define TICK_PERIOD (GetPeripheralClock() * SAMPLE_PERIOD) / 4000000
//TICK_PERIOD = 80000000 * 500 / 4000000 = 80* 500 / 4 = 20*500 = 10000
void TickInit(void) //タイマ4初期化
{
OpenTimer4(T4_ON | T4_PS_1_256, 31249); //1000/80000000*256*31249 =99.9968 msec
// OpenTimer4(T4_ON | T4_PS_1_8, 10000); //2msec
// OpenTimer4(T4_ON | T4_PS_1_8, TICK_PERIOD); //実測値:35μsec //オーバーフローエラー発生
ConfigIntTimer4(T4_INT_ON | T4_INT_PRIOR_1);
}
//---------------------------------------------------------------
void ProcessIO(void)
{
BYTE i;
App_Detect_Device();
switch(App_State_Keyboard)
{
case DEVICE_NOT_CONNECTED:
USBTasks();
if(DisplayDeatachOnce == FALSE)
{
lcd_clear();
lcd_cmd(0x80);
sprintf(Buf,"Device Det");
lcd_str(Buf);
// LCDDisplayString((BYTE*)"Device Detached ", LCD_LINE_ONE);
DisplayDeatachOnce = TRUE;
}
if(USBHostHID_ApiDeviceDetect()) /* True if report descriptor is parsed with no error */
{
App_State_Keyboard = DEVICE_CONNECTED;
DisplayConnectOnce = FALSE;
}
break;
case DEVICE_CONNECTED:
App_State_Keyboard = READY_TO_TX_RX_REPORT;
if(DisplayConnectOnce == FALSE)
{
lcd_clear();
lcd_cmd(0x80);
sprintf(Buf,"EX16 Boare ");//
lcd_str(Buf); //液晶表示
lcd_cmd(0xC0); //2行目の先頭へ
sprintf(Buf,"USB HIDHost Demo"); //
lcd_str(Buf); // 開始メッセージ1行目表示
#ifdef DEBUG_MODE
UART2PrintString( "Explorer16 Board \r\n" );
UART2PrintString( "USB HIDHost Demo \r\n" );
#endif
DisplayConnectOnce = TRUE;
DisplayDeatachOnce = FALSE;
}
InitializeTimer(); // start 10ms timer to schedule input reports
break;
case READY_TO_TX_RX_REPORT:
if(!USBHostHID_ApiDeviceDetect())
{
App_State_Keyboard = DEVICE_NOT_CONNECTED;
// DisplayOnce = FALSE;
}
break;
case GET_INPUT_REPORT:
if(USBHostHID_ApiGetReport(Appl_raw_report_buffer.Report_ID,Appl_ModifierKeysDetails.interfaceNum,
Appl_raw_report_buffer.ReportSize, Appl_raw_report_buffer.ReportData))
{
/* Host may be busy/error -- keep trying */
}
else
{
App_State_Keyboard = INPUT_REPORT_PENDING;
}
USBTasks();
break;
case INPUT_REPORT_PENDING:
if(USBHostHID_ApiTransferIsComplete(&ErrorDriver,&NumOfBytesRcvd))
{
if(ErrorDriver ||(NumOfBytesRcvd != Appl_raw_report_buffer.ReportSize ))
{
ErrorCounter++ ;
if(MAX_ERROR_COUNTER <= ErrorDriver)
App_State_Keyboard = ERROR_REPORTED;
else
App_State_Keyboard = READY_TO_TX_RX_REPORT;
}
else
{
ErrorCounter = 0;
ReportBufferUpdated = TRUE;
App_State_Keyboard = READY_TO_TX_RX_REPORT;
if(DisplayConnectOnce == TRUE)
{
for(i=0;i<Appl_raw_report_buffer.ReportSize;i++)
{
if(Appl_raw_report_buffer.ReportData[i] != 0)
{
lcd_clear();
lcd_cmd(0x80);
DisplayConnectOnce = FALSE;
}
}
}
App_ProcessInputReport(); //キーボード入力検出・表示
App_PrepareOutputReport();
}
}
break;
case SEND_OUTPUT_REPORT: /* Will be done while implementing Keyboard */
if(USBHostHID_ApiSendReport(Appl_LED_Indicator.reportID,Appl_LED_Indicator.interfaceNum, Appl_LED_Indicator.reportLength,
(BYTE*)&Appl_led_report_buffer))
{
/* Host may be busy/error -- keep trying */
}
else
{
App_State_Keyboard = OUTPUT_REPORT_PENDING;
}
USBTasks();
break;
case OUTPUT_REPORT_PENDING:
if(USBHostHID_ApiTransferIsComplete(&ErrorDriver,&NumOfBytesRcvd))
{
if(ErrorDriver)
{
ErrorCounter++ ;
if(MAX_ERROR_COUNTER <= ErrorDriver)
App_State_Keyboard = ERROR_REPORTED;
// App_State_Keyboard = READY_TO_TX_RX_REPORT;
}
else
{
ErrorCounter = 0;
App_State_Keyboard = READY_TO_TX_RX_REPORT;
}
}
break;
case ERROR_REPORTED:
break;
default:
break;
}
}
/****************************************************************************
Function:
void App_PrepareOutputReport(void)
Description:
This function schedules output report if any LED indicator key is pressed.
Precondition:
None
Parameters:
None
Return Values:
None
Remarks:
None
***************************************************************************/
void App_PrepareOutputReport(void)
{
// if((READY_TO_TX_RX_REPORT == App_State_Keyboard) && (ReportBufferUpdated == TRUE))
if(ReportBufferUpdated == TRUE)
{
ReportBufferUpdated = FALSE;
if(LED_Key_Pressed)
{
App_State_Keyboard = SEND_OUTPUT_REPORT;
LED_Key_Pressed = FALSE;
}
}
}
/****************************************************************************
Function:
void App_ProcessInputReport(void)
Description:
This function processes input report received from HID device.
Precondition:
None
Parameters:
None
Return Values:
None
Remarks:
None
***************************************************************************/
void App_ProcessInputReport(void)
{
BYTE i;
BYTE data;
/* process input report received from device */
USBHostHID_ApiImportData(Appl_raw_report_buffer.ReportData, Appl_raw_report_buffer.ReportSize
,Appl_BufferModifierKeys, &Appl_ModifierKeysDetails);
USBHostHID_ApiImportData(Appl_raw_report_buffer.ReportData, Appl_raw_report_buffer.ReportSize
,Appl_BufferNormalKeys, &Appl_NormalKeysDetails);
for(i=0;i<(sizeof(Appl_BufferNormalKeys)/sizeof(Appl_BufferNormalKeys[0]));i++)
{
if(Appl_BufferNormalKeys[i] != 0)
{
if(Appl_BufferNormalKeys[i] == HID_CAPS_LOCK_VAL)
{
CAPS_Lock_Pressed = !CAPS_Lock_Pressed;
LED_Key_Pressed = TRUE;
Appl_led_report_buffer.CAPS_LOCK = CAPS_Lock_Pressed;
}else if(Appl_BufferNormalKeys[i] == HID_NUM_LOCK_VAL)
{
NUM_Lock_Pressed = !NUM_Lock_Pressed;
LED_Key_Pressed = TRUE;
Appl_led_report_buffer.NUM_LOCK = NUM_Lock_Pressed;
}else
{
/* check if key press was present in previous report */
// if key press was pressed in previous report neglect it ????
if(!App_CompareKeyPressedPrevBuf(Appl_BufferNormalKeys[i]))
{
//アスキーコードに変換-----------------------------------------------------------------------------
data = App_HID2ASCII(Appl_BufferNormalKeys[i]); // convert data to ascii
LCD_Display_Routine(data,Appl_BufferNormalKeys[i] );
}
}
}
else
{
if(i==0)
{
HeldKeyCount = 0;
}
else
{
if(Appl_BufferNormalKeys[i-1] == HeldKey)
{
if(HeldKeyCount < 3)
{
HeldKeyCount++;
}
else
{
//アスキーコードに変換-----------------------------------------------------------------------------
data = App_HID2ASCII(HeldKey); // convert data to ascii
LCD_Display_Routine(data,HeldKey );
}
}
else
{
HeldKeyCount = 0;
HeldKey = Appl_BufferNormalKeys[i-1];
}
}
break;
}
}
App_CopyToShadowBuffer();
App_Clear_Data_Buffer();
}
/****************************************************************************
Function:
void App_CopyToShadowBuffer(void)
Description:
This function updates the shadow buffers with previous reports.
Precondition:
None
Parameters:
None
Return Values:
None
Remarks:
None
***************************************************************************/
void App_CopyToShadowBuffer(void)
{
BYTE i;
for(i=0;i<(sizeof(Appl_BufferNormalKeys)/sizeof(Appl_BufferNormalKeys[0]));i++)
{
Appl_ShadowBuffer1[i] = Appl_BufferNormalKeys[i];
}
}
/****************************************************************************
Function:
BOOL App_CompareKeyPressedPrevBuf(BYTE data)
Description:
This function compares if the data byte received in report was sent in
previous report. This is to avoid duplication incase user key in strokes
at fast rate.
Precondition:
None
Parameters:
BYTE data - data byte that needs to be compared with previous
report
Return Values:
None
Remarks:
None
***************************************************************************/
BOOL App_CompareKeyPressedPrevBuf(BYTE data)
{
BYTE i;
for(i=0;i<(sizeof(Appl_BufferNormalKeys)/sizeof(Appl_BufferNormalKeys[0]));i++)
{
if(data == Appl_ShadowBuffer1[i])
{
return TRUE;
}
}
return FALSE;
}
/****************************************************************************
Function:
void App_Detect_Device(void)
Description:
This function monitors the status of device connected/disconnected
Precondition:
None
Parameters:
None
Return Values:
None
Remarks:
None
***************************************************************************/
void App_Detect_Device(void)
{
if(!USBHostHID_ApiDeviceDetect())
{
App_State_Keyboard = DEVICE_NOT_CONNECTED;
}
}
/****************************************************************************
Function:
void App_Clear_Data_Buffer(void)
Description:
This function clears the content of report buffer after reading
Precondition:
None
Parameters:
None
Return Values:
None
Remarks:
None
***************************************************************************/
void App_Clear_Data_Buffer(void)
{
BYTE i;
for(i=0;i<(sizeof(Appl_BufferNormalKeys)/sizeof(Appl_BufferNormalKeys[0]));i++)
{
Appl_BufferNormalKeys[i] = 0;
}
for(i=0;i<Appl_raw_report_buffer.ReportSize;i++)
{
Appl_raw_report_buffer.ReportData[i] = 0;
}
}
/****************************************************************************
Function:
BYTE App_HID2ASCII(BYTE a)
Description:
This function converts the HID code of the key pressed to coressponding
ASCII value. For Key strokes like Esc, Enter, Tab etc it returns 0.
Precondition:
None
Parameters:
BYTE a - HID code for the key pressed
Return Values:
BYTE - ASCII code for the key pressed
Remarks:
None
***************************************************************************/
BYTE App_HID2ASCII(BYTE a) //convert USB HID code (buffer[2 to 7]) to ASCII code
{
BYTE AsciiVal;
BYTE ShiftkeyStatus = 0;
if((Appl_BufferModifierKeys[MODIFIER_LEFT_SHIFT] == 1)||(Appl_BufferModifierKeys[MODIFIER_RIGHT_SHIFT] == 1))
{
ShiftkeyStatus = 1;
}
if(a>=0x1E && a<=0x27)
{
if(ShiftkeyStatus)
{
switch(a)
{
case Symbol_Exclamation: AsciiVal = 0x21;
break;
case Symbol_AT: AsciiVal = 0x40;
break;
case Symbol_Pound: AsciiVal = 0x23;
break;
case Symbol_Dollar: AsciiVal = 0x24;
break;
case Symbol_Percentage: AsciiVal = 0x25;
break;
case Symbol_Cap: AsciiVal = 0x5E;
break;
case Symbol_AND: AsciiVal = 0x26;
break;
case Symbol_Star: AsciiVal = 0x2A;
break;
case Symbol_NormalBracketOpen: AsciiVal = 0x28;
break;
case Symbol_NormalBracketClose: AsciiVal = 0x29;
break;
default:
break;
}
return(AsciiVal);
}
else
{
if(a==0x27)
{
return(0x30);
}
else
{
return(a+0x13);
}
}
}
if((a>=0x59 && a<=0x61)&&(NUM_Lock_Pressed == 1))
{
return(a-0x28);
}
if((a==0x62) &&(NUM_Lock_Pressed == 1)) return(0x30);
if(a>=0x04 && a<=0x1D)
{
if(((CAPS_Lock_Pressed == 1)&&((Appl_BufferModifierKeys[MODIFIER_LEFT_SHIFT] == 0)&&
(Appl_BufferModifierKeys[MODIFIER_RIGHT_SHIFT] == 0)))
||((CAPS_Lock_Pressed == 0)&&((Appl_BufferModifierKeys[MODIFIER_LEFT_SHIFT] == 1) ||
(Appl_BufferModifierKeys[MODIFIER_RIGHT_SHIFT] == 1))))
return(a+0x3d); /* return capital */
else
return(a+0x5d); /* return small case */
}
if(a>=0x2D && a<=0x38)
{
switch(a)
{
case Symbol_HyphenUnderscore:
if(!ShiftkeyStatus)
AsciiVal = 0x2D;
else
AsciiVal = 0x5F;
break;
case Symbol_EqualAdd:
if(!ShiftkeyStatus)
AsciiVal = 0x3D;
else
AsciiVal = 0x2B;
break;
case Symbol_BracketOpen:
if(!ShiftkeyStatus)
AsciiVal = 0x5B;
else
AsciiVal = 0x7B;
break;
case Symbol_BracketClose:
if(!ShiftkeyStatus)
AsciiVal = 0x5D;
else
AsciiVal = 0x7D;
break;
case Symbol_BackslashOR:
if(!ShiftkeyStatus)
AsciiVal = 0x5C;
else
AsciiVal = 0x7C;
break;
case Symbol_SemiColon:
if(!ShiftkeyStatus)
AsciiVal = 0x3B;
else
AsciiVal = 0x3A;
break;
case Symbol_InvertedComma:
if(!ShiftkeyStatus)
AsciiVal = 0x27;
else
AsciiVal = 0x22;
break;
case Symbol_Tilde:
if(!ShiftkeyStatus)
AsciiVal = 0x60;
else
AsciiVal = 0x7E;
break;
case Symbol_CommaLessThan:
if(!ShiftkeyStatus)
AsciiVal = 0x2C;
else
AsciiVal = 0x3C;
break;
case Symbol_PeriodGreaterThan:
if(!ShiftkeyStatus)
AsciiVal = 0x2E;
else
AsciiVal = 0x3E;
break;
case Symbol_FrontSlashQuestion:
if(!ShiftkeyStatus)
AsciiVal = 0x2F;
else
AsciiVal = 0x3F;
break;
default:
break;
}
return(AsciiVal);
}
return(0);
}
/****************************************************************************
Function:
void LCD_Display_Routine(BYTE data , BYTE HIDData)
Description:
This function displays the key strokes on the LCD mounted on Explorer16
demo board.
Precondition:
None
Parameters:
BYTE data - ASCII code for the key pressed
BYTE HIDData - HID code for the key pressed, this is needed to take
action for keys like Esc, Enter, Tab etc.
Return Values:
None
Remarks:
***************************************************************************/
void LCD_Display_Routine(BYTE data , BYTE HIDData)
{
BYTE LineNum;
BYTE CharPos;
int i;
LineNum = ((currCharPos & 0x30) >> 4);
CharPos = currCharPos & 0x0F;
if(((HIDData>=0x1E && HIDData<=0x27) || (HIDData>=0x04 && HIDData<=0x1D) ||
(HIDData>=0x2D && HIDData<=0x38) ||
((HIDData>=0x59 && HIDData<=0x62)&&(NUM_Lock_Pressed == 1))) && (HIDData != 0x35)) //0x35: 漢字キー追加
{
lcd_data(data);
currCharPos++;
if(myColumnNum == (myColumnNum0 - 1))
{
strncat(myAllChar,Kaigyou,16); //改行記号\n 追加
myCharPos++;
myColumnNum = 0; //列番号リセット
myLineNum++;
if(myLineNum == 13)
{
//グラフィック液晶のStatic Text Widgetに表示
STATICTEXT *pSTE_1 = (STATICTEXT*)GOLFindObject(STE_1); //エディットボックスのオブジェクト検出
pSTE_1->hdr.state = ST_DRAW; //再描画により文字は左アラインにリセットされる
for(i = 0; i <1024; i++)tempBuf[i] = 0x00;
StSetText((STATICTEXT*)pSTE_1, myAllChar); //
SetState(pSTE_1, ST_DRAW);
}
}
sprintf(Buf,"%c",data);
myCharPos++;
myColumnNum++;
}
else if(HIDData == 0x29) // escape key pressed
{
lcd_clear();
lcd_cmd(0x80);
currCharPos = 0;
// sprintf(Buf,"HID = 0x%x, Key = ESC",HIDData,data,data);
}
else if (HIDData == 0x2C) //スペースが押された場合
{
lcd_data(0x20); // /0x20: アスキー文字のスペース
currCharPos++;
data = 0x20;
sprintf(Buf,"%c",data);
myCharPos++;
}
else if (HIDData == Symbol_Backspace) //バックスペースが押された場合
{
if(currCharPos != 0)
{
lcd_cmd(0b00010000);
lcd_data(0x20); // space ascii value 0x20
lcd_cmd(0b00010000);
currCharPos--;
}
sprintf(Buf,"%c",0x00); //0x20: アスキー文字のスペース
myCharPos--;
myColumnNum--;
if(myColumnNum < 0)
{
myColumnNum = myColumnNum0;
myLineNum--;
}
if(tempBuf[myCharPos] == '\n')myCharPos--;
tempBuf[myCharPos] = 0x00; //文字列終端記号\0をセット
}
else if((HIDData>=0x4F && HIDData<=0x52) ||
(( HIDData==0x5C || HIDData==0x5E || HIDData==0x5A || HIDData==0x60 )
&& (NUM_Lock_Pressed == 0)))
{
switch(HIDData)
{
case 0x4F : // Right Arrow
case 0x5E :
lcd_cmd(0b00010100);
currCharPos++;
sprintf(Buf,"HID = 0x%x, Key = Right Arrow",HIDData,data,data);
break;
case 0x50 : // Left Arrow
case 0x5C :
lcd_cmd(0b00010000);
currCharPos--;
sprintf(Buf,"HID = 0x%x, Key = Left Arrow",HIDData,data,data);
break;
case 0x52 : // Up Arrow
case 0x60 :
if(LineNum == 1)
{
// LCDShiftCursorUp(); //対応する関数なし
currCharPos = currCharPos - 16;
LineNum = 0;
}
sprintf(Buf,"HID = 0x%x, Key = Up Arrow",HIDData,data,data);
break;
case 0x51 : // Down Arrow
case 0x5A :
if(LineNum == 0)
{
// LCDShiftCursorDown(); //対応する関数なし
currCharPos = currCharPos + 16;
LineNum = 1;
}
sprintf(Buf,"HID = 0x%x, Key = Down Arrow",HIDData,data,data);
break;
default :
break;
}
}
else if(HIDData == Symbol_Return)
{
sprintf(Buf,"\n");
myCharPos++;
myColumnNum = 0;
myLineNum++;
if(myLineNum == 13)
{
//グラフィック液晶のStatic Text Widgetに表示
STATICTEXT *pSTE_1 = (STATICTEXT*)GOLFindObject(STE_1); //エディットボックスのオブジェクト検出
pSTE_1->hdr.state = ST_DRAW; //再描画により文字は左アラインにリセットされる
for(i = 0; i <1024; i++)tempBuf[i] = 0x00;
StSetText((STATICTEXT*)pSTE_1, myAllChar); //
SetState(pSTE_1, ST_DRAW);
}
// sprintf(Buf,"HID = 0x%x, Key = Return",HIDData,data,data);
}
else if(HIDData == Symbol_Kanji)
{
// sprintf(Buf,"HID = 0x%x, Key = Kanji",HIDData,data,data);
}
else if(HIDData == Symbol_Tab)
{
// sprintf(Buf,"HID = 0x%x, Key = Tab",HIDData,data,data);
}
else if(HIDData == Symbol_Delete)
{
// sprintf(Buf,"HID = 0x%x, Key = Delete",HIDData,data,data);
}
else if(HIDData == Symbol_PrintScr)
{
// sprintf(Buf,"HID = 0x%x, Key = PrintScr",HIDData,data,data);
}
else if(HIDData == Symbol_PauseBreak)
{
// sprintf(Buf,"HID = 0x%x, Key = PauseBreak",HIDData,data,data);
}
else if(HIDData == Symbol_ScrLK)
{
// sprintf(Buf,"HID = 0x%x, Key = ScrLK",HIDData,data,data);
}
else
{
sprintf(Buf,"HID = 0x%x, Key = ?",HIDData,data,data);
}
//グラフィック液晶のStatic Text Widgetに表示
STATICTEXT *pSTE_1 = (STATICTEXT*)GOLFindObject(STE_1); //エディットボックスのオブジェクト検出
pSTE_1->hdr.state = ST_DRAW; //再描画により文字は左アラインにリセットされる
strncat(myAllChar,Buf,65); //文字追加
StSetText((STATICTEXT*)pSTE_1, myAllChar); //
SetState(pSTE_1, ST_DRAW);
LineNum = ((currCharPos & 0x30) >> 4);
CharPos = currCharPos & 0x0F;
if((LineNum == 1) && (CharPos == 0x0))
{
lcd_cmd(0xC0);
currCharPos = 0x10;
}else if((LineNum == 2) && (CharPos == 0x0))
{
lcd_clear();
lcd_cmd(0x80);
currCharPos = 0;
}
if(currCharPos > 0x20)
{
lcd_clear();
lcd_cmd(0x80);
currCharPos = 0;
}
}
/****************************************************************************
Function:
BOOL USB_HID_DataCollectionHandler(void)
Description:
This function is invoked by HID client , purpose is to collect the
details extracted from the report descriptor. HID client will store
information extracted from the report descriptor in data structures.
Application needs to create object for each report type it needs to
extract.
For ex: HID_DATA_DETAILS Appl_ModifierKeysDetails;
HID_DATA_DETAILS is defined in file usb_host_hid_appl_interface.h
Each member of the structure must be initialized inside this function.
Application interface layer provides functions :
USBHostHID_ApiFindBit()
USBHostHID_ApiFindValue()
These functions can be used to fill in the details as shown in the demo
code.
Precondition:
None
Parameters:
None
Return Values:
TRUE - If the report details are collected successfully.
FALSE - If the application does not find the the supported format.
Remarks:
This Function name should be entered in the USB configuration tool
in the field "Parsed Data Collection handler".
If the application does not define this function , then HID cient
assumes that Application is aware of report format of the attached
device.
***************************************************************************/
BOOL USB_HID_DataCollectionHandler(void)
{
BYTE NumOfReportItem = 0;
BYTE i;
USB_HID_ITEM_LIST* pitemListPtrs;
USB_HID_DEVICE_RPT_INFO* pDeviceRptinfo;
HID_REPORTITEM *reportItem;
HID_USAGEITEM *hidUsageItem;
BYTE usageIndex;
BYTE reportIndex;
BOOL foundLEDIndicator = FALSE;
BOOL foundModifierKey = FALSE;
BOOL foundNormalKey = FALSE;
pDeviceRptinfo = USBHostHID_GetCurrentReportInfo(); // Get current Report Info pointer
pitemListPtrs = USBHostHID_GetItemListPointers(); // Get pointer to list of item pointers
BOOL status = FALSE;
/* Find Report Item Index for Modifier Keys */
/* Once report Item is located , extract information from data structures provided by the parser */
NumOfReportItem = pDeviceRptinfo->reportItems;
for(i=0;i<NumOfReportItem;i++)
{
reportItem = &pitemListPtrs->reportItemList[i];
if((reportItem->reportType==hidReportInput) && (reportItem->dataModes == HIDData_Variable)&&
(reportItem->globals.usagePage==USAGE_PAGE_KEY_CODES))
{
/* We now know report item points to modifier keys */
/* Now make sure usage Min & Max are as per application */
usageIndex = reportItem->firstUsageItem;
hidUsageItem = &pitemListPtrs->usageItemList[usageIndex];
if((hidUsageItem->usageMinimum == USAGE_MIN_MODIFIER_KEY)
&&(hidUsageItem->usageMaximum == USAGE_MAX_MODIFIER_KEY)) //else application cannot suuport
{
reportIndex = reportItem->globals.reportIndex;
Appl_ModifierKeysDetails.reportLength = (pitemListPtrs->reportList[reportIndex].inputBits + 7)/8;
Appl_ModifierKeysDetails.reportID = (BYTE)reportItem->globals.reportID;
Appl_ModifierKeysDetails.bitOffset = (BYTE)reportItem->startBit;
Appl_ModifierKeysDetails.bitLength = (BYTE)reportItem->globals.reportsize;
Appl_ModifierKeysDetails.count=(BYTE)reportItem->globals.reportCount;
Appl_ModifierKeysDetails.interfaceNum= USBHostHID_ApiGetCurrentInterfaceNum();
foundModifierKey = TRUE;
}
}
else if((reportItem->reportType==hidReportInput) && (reportItem->dataModes == HIDData_Array)&&
(reportItem->globals.usagePage==USAGE_PAGE_KEY_CODES))
{
/* We now know report item points to modifier keys */
/* Now make sure usage Min & Max are as per application */
usageIndex = reportItem->firstUsageItem;
hidUsageItem = &pitemListPtrs->usageItemList[usageIndex];
if((hidUsageItem->usageMinimum == USAGE_MIN_NORMAL_KEY)
&&(hidUsageItem->usageMaximum <= USAGE_MAX_NORMAL_KEY)) //else application cannot suuport
{
reportIndex = reportItem->globals.reportIndex;
Appl_NormalKeysDetails.reportLength = (pitemListPtrs->reportList[reportIndex].inputBits + 7)/8;
Appl_NormalKeysDetails.reportID = (BYTE)reportItem->globals.reportID;
Appl_NormalKeysDetails.bitOffset = (BYTE)reportItem->startBit;
Appl_NormalKeysDetails.bitLength = (BYTE)reportItem->globals.reportsize;
Appl_NormalKeysDetails.count=(BYTE)reportItem->globals.reportCount;
Appl_NormalKeysDetails.interfaceNum= USBHostHID_ApiGetCurrentInterfaceNum();
foundNormalKey = TRUE;
}
}
else if((reportItem->reportType==hidReportOutput) &&
(reportItem->globals.usagePage==USAGE_PAGE_LEDS))
{
usageIndex = reportItem->firstUsageItem;
hidUsageItem = &pitemListPtrs->usageItemList[usageIndex];
reportIndex = reportItem->globals.reportIndex;
Appl_LED_Indicator.reportLength = (pitemListPtrs->reportList[reportIndex].outputBits + 7)/8;
Appl_LED_Indicator.reportID = (BYTE)reportItem->globals.reportID;
Appl_LED_Indicator.bitOffset = (BYTE)reportItem->startBit;
Appl_LED_Indicator.bitLength = (BYTE)reportItem->globals.reportsize;
Appl_LED_Indicator.count=(BYTE)reportItem->globals.reportCount;
Appl_LED_Indicator.interfaceNum= USBHostHID_ApiGetCurrentInterfaceNum();
foundLEDIndicator = TRUE;
}
}
if(pDeviceRptinfo->reports == 1)
{
Appl_raw_report_buffer.Report_ID = 0;
Appl_raw_report_buffer.ReportSize = (pitemListPtrs->reportList[reportIndex].inputBits + 7)/8;
Appl_raw_report_buffer.ReportData = (BYTE*)malloc(Appl_raw_report_buffer.ReportSize);
Appl_raw_report_buffer.ReportPollRate = pDeviceRptinfo->reportPollingRate;
if((foundNormalKey == TRUE)&&(foundModifierKey == TRUE))
status = TRUE;
}
return(status);
}
/****************************************************************************
Function:
void InitializeTimer( void )
Description:
This function initializes the tick timer. It configures and starts the
timer, and enables the timer interrupt.
Precondition:
None
Parameters:
None
Returns:
None
Remarks:
None
***************************************************************************/
void InitializeTimer( void ) //タイマ4 → タイマ5に変更 //GDDXのインターバルタイマ(タイマ4)とバッティング回避
{
//TODO - PIC32 support
T5CON = 0x0; //Stop and Init Timer
// T4CON = 0x0; //Stop and Init Timer
T5CON = 0x0060;
// T4CON = 0x0060;
//prescaler=1:64,
//internal clock
TMR5 = 0; //Clear timer register
// TMR4 = 0; //Clear timer register
PR5 = 0x7FFF; //Load period register
//PR4 = 0x7FFF; //Load period register
//1000/80000000*64*0x7FFF(32767) = 26.2msec
// OpenTimer4(T4_ON | T4_PS_1_256, 31249); //1000/80000000*256*31249 =99.9968 msec
IPC5SET = 0x00000004; // Set priority level=1 and
// IPC4SET = 0x00000004; // Set priority level=1 and
IPC5SET = 0x00000001; // Set subpriority level=1
// IPC4SET = 0x00000001; // Set subpriority level=1
// Could have also done this in single
// operation by assigning IPC5SET = 0x00000005
// IFS0CLR = 0x00010000; // Clear the Timer5 interrupt status flag
// IEC0SET = 0x00010000; // Enable Timer5 interrupts
IFS0bits.T5IF = 0;
// IFS0bits.T4IF = 0;
IEC0bits.T5IE = 1;
// IEC0bits.T4IE = 1;
T5CONSET = 0x8000;//Start Timer
// T4CONSET = 0x8000;//Start Timer
return;
}
/****************************************************************************
Function:
void __attribute__((__interrupt__, auto_psv)) _T3Interrupt(void)
Description:
Timer ISR, used to update application state. If no transfers are pending
new input request is scheduled.
Precondition:
None
Parameters:
None
Return Values:
None
Remarks:
None
***************************************************************************/
#pragma interrupt _T5Interrupt ipl4 vector 20 //タイマ5 //割込みレベル:4 //ベクター番号:20
//#pragma interrupt _T4Interrupt ipl4 vector 16
void _T5Interrupt(void)
//void _T4Interrupt( void )
{
if(myMode == 0)
{
myMode = 1;
LATDbits.LATD3 = 0;
}
else
{
myMode = 0;
LATDbits.LATD3 = 1;
}
if (IFS0bits.T5IF)
// if (IFS0bits.T4IF)
{
IFS0bits.T5IF = 0;
// IFS0bits.T4IF = 0;
if(READY_TO_TX_RX_REPORT == App_State_Keyboard)
{
App_State_Keyboard = GET_INPUT_REPORT; // If no report is pending schedule new request
}
}
}
// USB Support Functions
BOOL USB_ApplicationEventHandler( BYTE address, USB_EVENT event, void *data, DWORD size )
{
switch( (INT)event )
{
case EVENT_VBUS_REQUEST_POWER:
// The data pointer points to a byte that represents the amount of power
// requested in mA, divided by two. If the device wants too much power,
// we reject it.
if (((USB_VBUS_POWER_EVENT_DATA*)data)->current <= (MAX_ALLOWED_CURRENT / 2))
{
return TRUE;
}
else
{
UART2PrintString( "\r\n***** USB Error - device requires too much current *****\r\n" );
}
break;
case EVENT_VBUS_RELEASE_POWER:
// Turn off Vbus power.
// The PIC24F with the Explorer 16 cannot turn off Vbus through software.
return TRUE;
break;
case EVENT_HUB_ATTACH:
UART2PrintString( "\r\n***** USB Error - hubs are not supported *****\r\n" );
return TRUE;
break;
case EVENT_UNSUPPORTED_DEVICE:
UART2PrintString( "\r\n***** USB Error - device is not supported *****\r\n" );
return TRUE;
break;
case EVENT_CANNOT_ENUMERATE:
UART2PrintString( "\r\n***** USB Error - cannot enumerate device *****\r\n" );
return TRUE;
break;
case EVENT_CLIENT_INIT_ERROR:
UART2PrintString( "\r\n***** USB Error - client driver initialization error *****\r\n" );
return TRUE;
break;
case EVENT_OUT_OF_MEMORY:
UART2PrintString( "\r\n***** USB Error - out of heap memory *****\r\n" );
return TRUE;
break;
case EVENT_UNSPECIFIED_ERROR: // This should never be generated.
UART2PrintString( "\r\n***** USB Error - unspecified *****\r\n" );
return TRUE;
break;
case EVENT_HID_RPT_DESC_PARSED:
#ifdef APPL_COLLECT_PARSED_DATA
return(APPL_COLLECT_PARSED_DATA());
#else
return TRUE;
#endif
break;
default:
break;
}
return FALSE;
}
//その他 FAT、グラフィックライブラリ関連のインクルードファイルは下記にあります。 //マイクロチップのライブラリダウンロードページ: Microchip Libraries for Applications 私がつかったバージョンは \microchip_solutions_v2013-02-15 です。 //GDDX関連のファイルは Microchip Graphics Display Designer X からダウンロードできます。 私がつかったバージョンは GDDX v.1.10 です //グラフィック液晶INT035TFTの関連情報は Displaytechのホームページ 及び DisplaytechのForum にあります。
<実行結果>

<プログラム例>
main() { }